Performance & Reliability
Conduit optimizations, performance budgets, and batched processing for scale.
Wrengler is engineered for scale and responsiveness. Performance targets are defined as budgets and achieved through conduit optimizations, batched processing, and careful lock management.
Performance Budgets
Key targets used for regression testing and optimization:
| Component | Target | Status |
|---|---|---|
| Bridge | <100ms per message | Achieved |
| Area calculation | <50ms per object | Achieved |
| Clustering | <5s for 100 objects | Achieved |
| Panel open | No freeze on large docs | Chunked index rebuild |
- Bridge: Script execution, UI thread marshaling, and serialization stay under 100ms total.
- Area: Face classification, stack detection, coverage check, and caching combine to <50ms per object with spatial indexing (RTree) and result caching.
- Clustering: RANSAC, DBSCAN (with spatial indexing), CRF, and height separation complete in <5s for 100 objects.
Conduit Performance (A+ Grade)
Display conduits are optimized for 1000+ plots and real-time interaction:
SmartPlotsConduit
- Batched drawing: For 100+ plots, boundaries are drawn in bulk by color; labels and highlights in separate passes. 15–25% faster at scale.
- Dynamic display mode: Labels are skipped during pan/zoom/rotate so the viewport stays smooth; they reappear when the view is static. 40–60% faster during interaction.
- Lock separation: Enable/disable uses a dedicated lock so it never blocks the draw thread or data updates (deadlock eliminated).
- Pre-computed geometry: Area, perimeter, and centroid are computed once when plots are set, not in the draw loop (~80% reduction in draw time for labels).
- Snapshot pattern: Draw code works from a snapshot of the data; the update thread can replace data without blocking draw.
NoiseMapConduit
- Mesh built outside lock: Mesh generation runs off the critical path; only a brief lock is used to swap in the new mesh. Draw is never blocked by updates.
- Separate locks: Mesh updates and ray visualization use independent locks so they don’t contend.
- O(log N) inspection: Spatial lookup uses the mesh spatial tree so inspection stays fast even for large receiver grids.
Benchmarks (1000 plots / 1000 receivers)
| Metric | Before | After |
|---|---|---|
| SmartPlots draw (static) | ~12ms | ~9ms |
| SmartPlots draw (dynamic) | ~12ms | ~4ms |
| Parameter update lag | 50–100ms | <5ms |
| NoiseMap inspection lag | 2–5ms | <1ms |
Large Documents & Selections
- Panel open: PresetIndexService builds its index in chunks (e.g. 250 objects per chunk) on the UI thread and yields between chunks so Rhino stays responsive.
- Area with many selected objects: Geometry is duplicated in batches (e.g. 40 per batch) on the UI thread and processed in the background; only the latest request’s result is sent. Previous requests are cancelled to avoid backlog.
ConduitPerformanceLogger
In DEBUG builds, key conduits (SunStudy, ViewStudy, NoiseMap, SmartPlots) wrap their draw logic with ConduitPerformanceLogger.Measure(). When PostDrawObjects or DrawOverlay exceeds the threshold (e.g. 2ms), a log entry is written to help find bottlenecks. Target frame budget is ~16ms per frame for 60 FPS.
Related
- Sunlight Analysis — GPU-accelerated analysis with live feedback
- Area Calculation — Semantic and area features
- Diagnostics — Diagnostic commands and observability