# Ifcos Errors Performance

> >

- **Type:** Skill
- **Install:** `agentstack add skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-ifcos-errors-performance`
- **Verified:** Pending review
- **Seller:** [Impertio-Studio](https://agentstack.voostack.com/s/impertio-studio)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Impertio-Studio](https://github.com/Impertio-Studio)
- **Source:** https://github.com/Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package/tree/main/skills/ifcopenshell/errors/ifcos-errors-performance
- **Website:** https://github.com/OpenAEC-Foundation

## Install

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

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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)

```python
# 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

```python
# 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)

```python
# 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

```python
# 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

```python
# 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

```python
# 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 | CURVES_SURFACES_AND_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

```python
# 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

```python
# 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

```python
# 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

```python
# 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.

- **Author:** [Impertio-Studio](https://github.com/Impertio-Studio)
- **Source:** [Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package](https://github.com/Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package)
- **License:** MIT
- **Homepage:** https://github.com/OpenAEC-Foundation

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

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** yes
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-ifcos-errors-performance
- Seller: https://agentstack.voostack.com/s/impertio-studio
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
