AgentStack
SKILL unreviewed MIT Self-run

Ifcos Errors Performance

skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-ifcos-errors-performance · by Impertio-Studio

>

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-ifcos-errors-performance

Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Dangerous shell/eval execution.

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Ifcos Errors Performance? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

IfcOpenShell Performance Optimization

Quick Reference

Decision Tree: Geometry Processing Strategy

Processing IFC geometry?
├── Single element (interactive/debug)?
│   └── ifcopenshell.geom.create_shape(settings, element)
│
├── Multiple elements (10+)?
│   └── ALWAYS use ifcopenshell.geom.iterator
│       ├── Need all elements? → iterator(settings, model, cpu_count())
│       └── Need specific types? → iterator(settings, model, cpu_count(), include=filtered)
│
└── No geometry needed (data extraction only)?
    └── Skip geometry entirely — use by_type() + get_psets()

Decision Tree: Large File Strategy

File size?
├──  2 GB (very large)
    ├── Needs full model? → 32+ GB RAM required
    ├── Needs subset? → Extract IDs first, process in chunks
    └── Geometry? → Process by type in sequence, gc.collect() between types

Critical Warnings

  • ALWAYS use ifcopenshell.geom.iterator for batch geometry processing (10+ elements). NEVER call create_shape() in a loop for bulk operations — iterator is 5-10x faster.
  • ALWAYS pass multiprocessing.cpu_count() to the iterator for optimal parallelism. Reduce thread count only on memory-constrained systems.
  • ALWAYS cache by_type() results when accessing the same type multiple times. The call is fast (O(1) internal index), but repeated calls add overhead in tight loops.
  • ALWAYS batch spatial containment and type assignments. Pass a list of products to a single API call instead of calling per-element.
  • NEVER store all geometry shapes in memory simultaneously. Process each shape and discard immediately.
  • NEVER use get_info(recursive=True) on large files — it materializes the entire entity graph into Python dicts.
  • NEVER open the same large file multiple times. Open once and pass the model reference.
  • ALWAYS call gc.collect() after releasing large models or between geometry processing batches.

Essential Patterns

Pattern 1: Geometry Iterator (Batch Processing)

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.geom
import multiprocessing

model = ifcopenshell.open("model.ifc")
settings = ifcopenshell.geom.settings()

iterator = ifcopenshell.geom.iterator(
    settings, model, multiprocessing.cpu_count()
)

if iterator.initialize():
    while True:
        shape = iterator.get()
        element = model.by_id(shape.id)
        verts = shape.geometry.verts   # Flat: [x1,y1,z1, x2,y2,z2, ...]
        faces = shape.geometry.faces   # Flat: [i1,i2,i3, ...]
        # Process immediately, do NOT accumulate shapes
        if not iterator.next():
            break

Pattern 2: Filtered Geometry Processing

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.geom
import multiprocessing

model = ifcopenshell.open("large_model.ifc")
settings = ifcopenshell.geom.settings()

# Process only walls: reduces memory and time
walls = model.by_type("IfcWall")
iterator = ifcopenshell.geom.iterator(
    settings, model, multiprocessing.cpu_count(),
    include=walls
)

if iterator.initialize():
    while True:
        shape = iterator.get()
        # Process shape...
        if not iterator.next():
            break

Pattern 3: Efficient Property Extraction (No Geometry)

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.util.element

model = ifcopenshell.open("large_model.ifc")

# Build pset index ONCE from relationship entities
pset_rels = model.by_type("IfcRelDefinesByProperties")
pset_map = {}
for rel in pset_rels:
    for obj in rel.RelatedObjects:
        if obj.id() not in pset_map:
            pset_map[obj.id()] = []
        pset_map[obj.id()].append(rel.RelatingPropertyDefinition)

# Now O(1) lookup per element instead of traversing relationships each time

Pattern 4: Batch API Operations

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.api

model = ifcopenshell.open("model.ifc")
storey = model.by_type("IfcBuildingStorey")[0]
walls = list(model.by_type("IfcWall"))

# CORRECT: Single API call for all elements
ifcopenshell.api.run("spatial.assign_container", model,
    relating_structure=storey, products=walls)
# Creates ONE IfcRelContainedInSpatialStructure for all walls

# CORRECT: Batch type assignment
wall_type = model.by_type("IfcWallType")[0]
ifcopenshell.api.run("type.assign_type", model,
    related_objects=walls, relating_type=wall_type)

Pattern 5: Memory Management for Large Files

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.util.element
import gc

def extract_wall_data(filepath):
    """Extract wall data from large file, then release model."""
    model = ifcopenshell.open(filepath)

    data = []
    for wall in model.by_type("IfcWall"):
        psets = ifcopenshell.util.element.get_psets(wall)
        data.append({
            "guid": wall.GlobalId,
            "name": wall.Name,
            "properties": psets
        })

    # Release model and force garbage collection
    del model
    gc.collect()

    return data  # Work with plain Python dicts from here

Pattern 6: Sequential Type Processing for Very Large Files

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.geom
import gc

model = ifcopenshell.open("huge_model.ifc")

element_types = ["IfcWall", "IfcSlab", "IfcColumn", "IfcBeam"]
for etype in element_types:
    elements = model.by_type(etype)
    if not elements:
        continue

    settings = ifcopenshell.geom.settings()
    iterator = ifcopenshell.geom.iterator(
        settings, model, 4, include=elements
    )

    if iterator.initialize():
        while True:
            shape = iterator.get()
            # Process and store results immediately
            if not iterator.next():
                break

    # Force GC between types to control peak memory
    gc.collect()

Performance Reference Tables

File Size vs Resource Usage

| File Size | Approx Elements | RAM Usage | Load Time | Notes | |-----------|----------------|-----------|-----------|-------| | 2 GB | > 500,000 | 16+ GB | 60s+ | Process by type, subprocess isolation |

Geometry Iterator vs create_shape()

| Aspect | create_shape() | geom.iterator | |--------|-----------------|-----------------| | Use case | Single element, interactive | Batch processing, export | | Multi-threading | No | Yes (OpenMP, multi-core) | | Geometry caching | No | Yes (reuses identical geometry) | | Error handling | Exception per element | Skips failed elements automatically | | Speed (1000 elements) | ~60s (sequential) | ~8s (8 cores) | | Memory per call | Lower overhead | Better amortized for many elements |

Geometry Settings for Performance

| Setting | Effect | Performance Impact | |---------|--------|-------------------| | disable-opening-subtractions | Skips boolean CSG operations | Major speedup, less accurate geometry | | use-world-coords | Applies global transforms | Slight overhead, but avoids manual transform | | weld-vertices | Merges duplicate vertices | Smaller output, slight processing cost | | apply-default-materials | Adds material data | Required for glTF, adds overhead | | dimensionality | Controls output complexity | CURVESSURFACESAND_SOLIDS is slowest |

Query Performance

| Method | Complexity | Notes | |--------|-----------|-------| | model.by_type("IfcWall") | O(1) | Uses internal class index | | model.by_id(42) | O(1) | Uses internal ID map | | model.by_guid("3Oe$...") | O(1) | Uses GUID index | | for e in model if e.is_a("IfcWall") | O(n) | NEVER use — iterates ALL entities | | ifcopenshell.util.element.get_psets(wall) | O(k) | Traverses k relationships per call | | ifcopenshell.util.selector.filter_elements(model, query) | O(n) | Full scan, but expressive queries |


Common Operations

Profiling IFC Operations

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import time

model = ifcopenshell.open("model.ifc")

# Time file loading
start = time.perf_counter()
model = ifcopenshell.open("model.ifc")
load_time = time.perf_counter() - start
print(f"Load time: {load_time:.2f}s")

# Time by_type queries
start = time.perf_counter()
walls = model.by_type("IfcWall")
query_time = time.perf_counter() - start
print(f"by_type query: {query_time:.6f}s for {len(walls)} walls")

# Time geometry processing
import ifcopenshell.geom
import multiprocessing

settings = ifcopenshell.geom.settings()
start = time.perf_counter()
iterator = ifcopenshell.geom.iterator(
    settings, model, multiprocessing.cpu_count()
)
count = 0
if iterator.initialize():
    while True:
        shape = iterator.get()
        count += 1
        if not iterator.next():
            break
geom_time = time.perf_counter() - start
print(f"Geometry: {count} shapes in {geom_time:.2f}s "
      f"({count/geom_time:.0f} shapes/sec)")

Controlling Thread Count for Memory

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.geom
import multiprocessing
import os

model = ifcopenshell.open("large_model.ifc")
settings = ifcopenshell.geom.settings()

# Check available memory (Linux/macOS)
try:
    import psutil
    available_gb = psutil.virtual_memory().available / (1024**3)
except ImportError:
    available_gb = 8  # Conservative fallback

# Scale threads to available memory
# Each thread can use 500MB-1GB for geometry processing
max_threads = multiprocessing.cpu_count()
safe_threads = min(max_threads, max(1, int(available_gb / 1.0)))

iterator = ifcopenshell.geom.iterator(
    settings, model, safe_threads
)

Subprocess Isolation for Very Large Files

# IfcOpenShell v0.8+: all schema versions
import subprocess
import json

# Process geometry in a subprocess to guarantee memory cleanup
# Python's GC may not release all C++ allocated memory
result = subprocess.run(
    ["python", "-c", """
import ifcopenshell
import ifcopenshell.geom
import json

model = ifcopenshell.open("huge_model.ifc")
settings = ifcopenshell.geom.settings()
walls = model.by_type("IfcWall")
iterator = ifcopenshell.geom.iterator(settings, model, 4, include=walls)

data = []
if iterator.initialize():
    while True:
        shape = iterator.get()
        element = model.by_id(shape.id)
        data.append({"guid": element.GlobalId, "verts": len(shape.geometry.verts)})
        if not iterator.next():
            break

print(json.dumps(data))
"""],
    capture_output=True, text=True
)
data = json.loads(result.stdout)
# Subprocess memory is fully reclaimed by OS on exit

Disabling Expensive Geometry Operations

# IfcOpenShell v0.8+: all schema versions
import ifcopenshell
import ifcopenshell.geom

model = ifcopenshell.open("model.ifc")
settings = ifcopenshell.geom.settings()

# Skip boolean operations (opening subtractions) for speed
# Doors/windows won't create holes in walls, but processing is much faster
settings.set("disable-opening-subtractions", True)

# Use world coordinates to avoid manual transform calculations
settings.set("use-world-coords", True)

Version Notes

Schema Sensitivity

This skill has low schema sensitivity. Performance patterns apply equally to IFC2X3, IFC4, and IFC4X3 files. The geometry iterator, caching strategies, and memory management techniques are schema-independent.

IfcOpenShell Version Notes

| Feature | Version | Notes | |---------|---------|-------| | geom.iterator | All versions | Core performance feature since early releases | | geom.settings() | All versions | String-based setting names in v0.8+ | | by_type() class index | All versions | O(1) lookup, always available | | include filter on iterator | v0.7+ | Filter elements before geometry processing | | Subprocess isolation | Any | Python-level pattern, not IfcOpenShell-specific |


Reference Links

  • [Performance Method Signatures](references/methods.md) — Complete API signatures for geometry processing and querying
  • [Working Performance Examples](references/examples.md) — End-to-end optimization examples for real scenarios
  • [Performance Anti-Patterns](references/anti-patterns.md) — Common performance mistakes and how to avoid them

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.