Skip to content

Benchmark Report — Visualization (v1.11.0)

Date: 2026-07-12 Package: mineproductivity.visualization (software v1.11.0) Scenarios: benchmark/scenarios/visualization/ Environment: Windows 11 (AMD64), CPython 3.12.10, mineproductivity editable-installed. Single process, no other load control — reference numbers for order-of-magnitude regression tracking, not a controlled lab measurement.

Both scenarios are standalone scripts (the mineproductivity.benchmark harness package is not yet implemented — see benchmark/README.md); re-run them with:

python benchmark/scenarios/visualization/dashboard_repository_latency.py
python benchmark/scenarios/visualization/render_parallel_throughput.py

1. DashboardRepository.get()/list() latency

Populations span "a team" (10³ dashboards) through "a whole enterprise, never pruned" (10⁵). get() figures are means over 10,000 calls; list() over 5.

boards get (µs) list all (ms) list by_owner (ms) owner matches
1,000 0.11 0.02 0.15 500
10,000 0.10 0.10 1.20 5,000
100,000 0.11 1.54 19.56 50,000

Reading: get() — the hot open-a-dashboard path — is flat (~0.10 µs) across a 100× population spread, the O(1) bound design spec §29 requires. list() is linear by core.BaseRepository's own contract — the discovery path (§27), not the open hot path. Identical shape to every other package's repository benchmark, as expected under the shared core.InMemoryRepository reference.

2. Multi-widget render throughput (sequential vs. parallel)

The same N widgets rendered through RenderingPipeline.render (visualization dispatch → PresentationModel → renderer dispatch → RenderedOutput). The example-local view and renderer are trivial, isolating pipeline dispatch overhead from a real charting backend's cost. Parallel runs over an 8-worker ThreadPoolExecutor.

widgets sequential (ms) seq renders/s parallel (ms) par renders/s
50 0.21 234,852 2.78 17,996
200 0.98 203,707 6.44 31,069
1,000 4.04 247,739 19.19 52,099

Reading: sequential render throughput is ~200k–248k renders/s — the pipeline is a pure two-hop dispatch with no persistence, so it is the fastest hot path in the platform. The threaded path is slower here for the familiar reason: with a sub-microsecond pure-Python view and renderer, every render holds the GIL, so thread parallelism only adds pool overhead. The benchmark's point is correctness under concurrency, not speedup: Visualization/Renderer instances are stateless and share no mutable state across calls (design spec §29), so a dashboard's widgets render independently without contention. Wall-clock speedup materializes only when the concrete renderer releases the GIL (a native charting/rasterization library) — exactly the backend boundary this package keeps out of its own code (§3.1, §4).

Regression guidance

Re-run both scenarios before each release touching visualization; investigate if get() exceeds ~1 µs at any population, or if sequential render throughput drops below ~50k renders/s for the trivial view/renderer on comparable hardware (a sign the two-hop dispatch path regressed).