181 lines
10 KiB
Markdown
181 lines
10 KiB
Markdown
# Architecture background geometry cache
|
||
|
||
Scope: [issue 44](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/44).
|
||
Production/test candidate: `636093aae67aa48fa1d35e403a205227e81d04de`, based on
|
||
`c0908f101ac376afb8021e60e454e2a176e49d45`. The base includes the separately
|
||
unaccepted outgoing-drag contribution for issue 40. This is a contribution
|
||
experiment and repair, not an integrated release or full FPS acceptance.
|
||
|
||
## Question and evidence
|
||
|
||
The [preceding core probe](../architecture-perf-20260925/README.md) measured
|
||
approximately 4.26ms median for preparation/projection/routing in an eight-card
|
||
approximation. It did not reproduce the reported severe slowdown. Source review
|
||
then identified repeated grid construction on every canvas redraw, despite the
|
||
grid's independence from model edits, selection and pointer position.
|
||
|
||
The standalone headless Iced probe copies the former grid loop: background fill,
|
||
then one radius-0.65 circle per grid point, with the same spacing, pan remainder
|
||
and colors. It measures geometry construction independently from offscreen
|
||
rendering/readback, using the actual compiled development-profile Iced renderer.
|
||
It creates no desktop window and sends no input. Three warmups precede 20 samples
|
||
per phase. The timer includes construction and returning geometry; returned
|
||
geometry destruction occurs afterwards. Sorted index `ceil((n-1)*p)` supplies
|
||
reported percentiles. Renderer startup is outside the timed phases.
|
||
|
||
`grid-performance-01.log`, produced by `grid_render_probe_v1.rs`, records:
|
||
|
||
| Canvas, zoom | Dots | Fresh geometry p50 ms | Cache retrieval p50 ms |
|
||
| --- | ---: | ---: | ---: |
|
||
| 1900x660, 1.0 | 2,240 | 67.8095 | 0.0001 |
|
||
| 1900x660, 0.5 | 6,528 | 192.5581 | 0.0001 |
|
||
| 1440x900, 1.0 | 2,318 | 66.2206 | 0.0002 |
|
||
| 1440x900, 0.5 | 6,695 | 219.1771 | 0.0002 |
|
||
|
||
Cold and warm cached grid pixels equal the uncached result byte for byte in all
|
||
four cases. Cache misses remain comparable to fresh construction; caching does
|
||
not improve continuously changing camera inputs. Offscreen screenshot/readback
|
||
cost remains substantial and variable. It must not be converted to native FPS.
|
||
|
||
## Candidate comparison and chosen change
|
||
|
||
1. Rebuild each circle every draw: exact current appearance, but the measured
|
||
repeated CPU cost alone is large in this development build.
|
||
2. Batch circles into one path: keeps the same pixels in this experiment but is
|
||
materially slower. `grid_render_probe.rs` and `grid-performance-02.log` retain
|
||
this rejected candidate. Its construction medians range from 274.66ms to
|
||
1,225.53ms, versus 63.82–178.24ms for the original loop in the same run.
|
||
3. Cache background geometry while camera and size stay identical: selected.
|
||
It preserves the original painter and removes its repeated construction from
|
||
stationary-camera interactions. It adds a small local cache, not a second
|
||
geometry implementation or a model-level cache.
|
||
|
||
`diagram/grid.rs` owns an Iced geometry cache and an exact raw `(zoom, pan)` key.
|
||
Iced's cache checks exact frame size. Camera changes explicitly clear it. The
|
||
colors and dot radius remain compile-time constants; future runtime styling
|
||
must invalidate this cache too. The conservative key rebuilds after a whole
|
||
grid-period pan and after zoom changes within the minimum-spacing clamp. No
|
||
fractional coordinates are rounded or tolerance-compared.
|
||
|
||
Drawing order becomes `[cached background and dots, live diagram, warnings]`.
|
||
The opaque background is in the first geometry, so it cannot cover the dots.
|
||
Existing pan/zoom transforms still apply only to the live model geometry.
|
||
The cache lives in the retained canvas State; model revisions and selections
|
||
do not invalidate it. Existing focus/suspension tree resets cause a safe cold
|
||
rebuild. No routing, model semantics, hit testing or gesture admission changes.
|
||
|
||
`production_grid_probe.rs` imports the actual candidate cache. Its exploratory
|
||
run 03 was performed before the source commit and formatting; the raw log is
|
||
retained as local precommit evidence, not relabeled as a binary from the commit.
|
||
The same source is supplied for reproduction at the identified candidate.
|
||
|
||
The separately recompiled run 04 imports the committed `636093aa` cache and ran
|
||
after the full desktop test process exited, before Clippy/build compilation.
|
||
`grid-performance-04.log` records exact baseline/cached pixels and these medians:
|
||
|
||
| Canvas, zoom | Fresh geometry ms | Production cache hit ms | Changing-pan rebuild ms |
|
||
| --- | ---: | ---: | ---: |
|
||
| 1900x660, 1.0 | 61.8281 | 0.0002 | 59.2995 |
|
||
| 1900x660, 0.5 | 158.8603 | 0.0002 | 163.4359 |
|
||
| 1440x900, 1.0 | 50.5385 | 0.0002 | 53.5840 |
|
||
| 1440x900, 0.5 | 168.4092 | 0.0002 | 175.2457 |
|
||
|
||
These results support the same bounded conclusion as the exploratory trials.
|
||
The run record preserves linked-library, driver and log hashes; timing noise
|
||
and screenshot readback remain explicit limitations.
|
||
Run 04 directly compares the production cache's cold pixels; its generic
|
||
cold-and-warm marker refers to the Iced-cache control. Warm production-cache
|
||
pixel parity is established separately by the committed grid tests.
|
||
|
||
## Verification and boundaries
|
||
|
||
Three committed headless tests check:
|
||
|
||
- Cache construction count through 18 exact camera/size changes, including
|
||
negative/fractional pan, zero-pan zoom changes, the minimum-spacing transition,
|
||
independent width/height resizing and return to previous dimensions.
|
||
- Exact RGBA equality against an independent copy of the legacy loop and
|
||
unsplit geometry. The scenes contain opaque cards, crossing edges, text,
|
||
translucent overdraw, selection handles and a warning overlay. Foreground
|
||
edits must visibly change pixels while retaining the background cache.
|
||
- The actual `DiagramCanvas` with one retained State: selection and model
|
||
revision changes must alter rendered pixels without rebuilding the grid;
|
||
pan and resize must rebuild it. This is drawing/scene-invalidation evidence,
|
||
not an event-driven native gesture test.
|
||
|
||
Fresh read-only independent review found no concrete cache-key, lifetime,
|
||
ordering or test-oracle defect. It checked the corresponding Iced 0.14 cache
|
||
and mesh-layer implementations. This review does not establish execution.
|
||
At `636093aa`, `grid-tests-01.log` passes all three targeted tests in 2.97s.
|
||
`grid-desktop-01.log` passes the full desktop suite in 362.14s: 1,543 passed,
|
||
zero failed, seven existing manual/diagnostic tests ignored, none filtered out.
|
||
All 1,550 distinct test names were counted; `context.json` lists the seven
|
||
ignored cases and records raw log hashes. This is desktop regression evidence;
|
||
it does not relabel the ignored checks as passing or establish native FPS.
|
||
The [independent review](independent-review.md) states its exact scope.
|
||
|
||
The initial strict Clippy run (`grid-clippy-01.log`) failed on two uses of
|
||
`chunks_exact(4)` in the new test helper. Test-only successor
|
||
`336720559bcec511949caa8a42bee8a55c3822da` uses `as_chunks::<4>()`; it leaves
|
||
production inputs unchanged. The original full-suite result remains associated
|
||
with `636093aa`, not relabeled as execution at the successor.
|
||
At the successor, strict all-target Clippy passes in 2m01s
|
||
(`grid-clippy-02.log`) and the three affected grid tests pass again in 4.13s
|
||
(`grid-tests-02.log`). No warning suppression or test exclusion was introduced.
|
||
|
||
The normal Windows GUI build at `33672055` also passes in 2m15s
|
||
(`desktop-build-02.log`). The executable and required `libunwind.dll` are staged
|
||
locally for later native verification, but this candidate has not been launched.
|
||
The executable SHA-256 is
|
||
`78548e93d4b57130ed507ed0f29eddbdbafb4721b38b0cd6d06101d5324114dd`;
|
||
`context.json` records both staged file hashes. Staging is not publication of a
|
||
new runnable release or native acceptance.
|
||
|
||
Remaining limits: the user's exact saved scene is unavailable; these results do
|
||
not establish end-to-end native FPS. Continuous pan/zoom still pays the cold
|
||
construction cost. Native desktop verification remains paused after user Escape.
|
||
Neither issue 40 nor issue 44 is closed by this headless experiment. Linux/WSL
|
||
remains deferred by the user. No published release has been replaced.
|
||
|
||
## Environment and reproduction
|
||
|
||
The subsequent [cold-construction and pan experiments](COLD-PAN.md) compare
|
||
additional approaches, including a renderer-translated cache. They preserve
|
||
their own pixel differences, timing limits and adoption gates; they do not
|
||
change the production implementation verified above.
|
||
|
||
Windows 10.0.26200, Rust 1.98.1, x86_64-pc-windows-gnullvm, development profile
|
||
with debug information disabled. The exposed CPU is Intel Core i7-10870H with
|
||
4 cores/threads; Windows reports VMware SVGA 3D, driver 9.17.11.4. The headless
|
||
renderer identifies itself as `wgpu`; the probe does not identify its selected
|
||
adapter or equate it with the desktop presenter's adapter. Other OS workloads
|
||
were not controlled, so measured outliers are preserved.
|
||
|
||
At the candidate source, the normal gates are:
|
||
|
||
```powershell
|
||
cargo test --locked --offline -p oa-desktop diagram::grid::tests -- --test-threads=1
|
||
cargo test --locked --offline -p oa-desktop -- --test-threads=1
|
||
cargo clippy --locked --offline -p oa-desktop --all-targets -- -D warnings
|
||
cargo build --locked --offline -p oa-desktop --bin arcadia-studio
|
||
```
|
||
|
||
For the standalone probes, first build the desktop dependencies in that profile.
|
||
Compile with `rustc --edition=2024 -C opt-level=0`, supplying `--extern iced=...`
|
||
and `--extern tokio=...` for the matching rlibs, plus `-L dependency=...` for
|
||
their directory. On this toolchain the link also needs `-C linker=clang.exe`
|
||
and `-L native=.../windows_x86_64_gnullvm-0.52.6/lib`. The original inputs were
|
||
`libiced-594f7d417d69ed72.rlib` and `libtokio-5e0ca96735e3073a.rlib` from
|
||
`target/debug/deps`. Run the resulting executable with argument `20`.
|
||
The production probe's relative module path requires compiling it at its
|
||
versioned location. Keep linker and runtime DLLs on PATH.
|
||
|
||
The first experimental compile failed because the configured futures crate
|
||
lacked its executor feature and an inherent screenshot method shadowed the
|
||
Headless trait method. Using the existing Tokio runtime and explicitly calling
|
||
`Headless::screenshot` corrected those driver errors. A second link failed for
|
||
the Windows import library search path; `grid-build-02.log` retains that failure.
|
||
Adding the native library path allowed subsequent probes to run. These failures
|
||
occurred in the experimental driver, before execution; they are not passing
|
||
application checks.
|