Repository navigation
Perf 26: bound shared mesh admission once, concurrent refresh queries - #108
Conversation
axisrow
left a comment
There was a problem hiding this comment.
Verdict: approved
Perf-26 promotion, three independent optimizations reviewed against upstream/master; no behaviour contract is weakened.
- Mesh admission (
crates/engine/src/query/snapshot.rs): validation, hashing and the byte copy now run exactly once per distinct digest; equal bytes under an admitted digest reuse the entry (their verdict carries over because the bytes are equal), and different bytes under one digest are refused asBlobInvalidon the reuse path — the same verdict the old per-occurrence path reached, minus the repeated work. The new tamper test pins the refusal. - Bounds: local bounds cached per digest and translated once per element. For a translation-only placement this is exact, not an approximation: IEEE addition is monotone, so translating the local min/max corners gives the same AABB the per-vertex scan produced, and a non-finite vertex still fails with the same
NumericUncertainthrough the cornerapply_point. The shared-mesh test pins the exact 200 mm shift and unchanged Y/Z extents. - Concurrent refresh (
apps/beamcraft-ui/src/source.rs): two independent CLI processes now run underthread::scope, a panicked worker maps to a typed error instead of poison, and the refresh waits for the slower query — correctly documented. - On-demand redraw (
apps/beamcraft-ui/src/app.rs): every background job wakes the UI withctx.request_repaint(),resizeearly-returns on an unchanged size and setsviewport_dirtyonly on a real change, so the dirty flag is not defeated by per-frame resizes; camera fit, load, renderer swap and orbit/pan/zoom all mark it. The idle-frame comment documents why the unconditional repaint is gone, and the FPS meter honestly became viewport redraws/s with a sane idle-spike guard.
Note, not a finding: no CI checks have reported on the branch yet; this approval rests on the code review above and on the same code having run in the fork since its perf-26 slice.
|
Thank you — the engine change reads correctly (one verification per distinct mesh digest, and translating the local bounds is exact because rounded addition is monotone). It now conflicts with master in |
The snapshot builder validated, hashed and copied every element's mesh blob before looking in the registry, and rescanned every vertex per element for world bounds, so N elements sharing one mesh paid N inspections, N SHA-256 computations, N copies and N per-vertex scans (issue 26, finding 4). Look in the registry first: a digest already admitted names verified bytes, equal bytes reuse the entry, and different bytes under one digest are still refused as tampered content - only genuinely new content pays the structural check, the hash and the copy. Compute the mesh-local bounds once per distinct mesh and translate them per translation-only placement; addition is monotone, so the translated corners are exactly the bounds the per-vertex scan produced, and a non-finite sum fails the same way. Measured on Apple M5, ViewSnapshot::build of 10,000 elements sharing one mesh, release build: 73.4 ms before, 18.1 and 19.9 ms across two runs after (73 percent less). 10,000 distinct meshes do not regress; that path still validates and hashes every blob once. Two new unit tests pin the reuse and the forged-digest refusal. (cherry picked from commit 297067f)
source::reload read the snapshot and then listed the definitions in sequence, so every refresh paid two full CLI inspections of the same store one after the other (issue 26, finding 2, refresh part). Both queries are independent CLI processes; run them in scoped threads and wait for the slower one. A panicked worker is reported as its typed failure, and one query failing still never hides the other. The click selection path added by V05.2 still runs its own inspections; removing that duplicate work is the remaining finding 2 item. Measured on the 100-element store, same harness either side (warm caches, release build): 398.9 ms sequential, 186.1 ms concurrent, 53 percent less wall time. (cherry picked from commit a7e2865)
e39a54f to
a0728dc
Compare
axisrow
left a comment
There was a problem hiding this comment.
Verdict: changes requested (PR metadata only; the two carried commits are unchanged)
Range-diffed against the previously reviewed head (e39a54f):
- The two remaining commits are patch-identical to what I approved (
=in the range-diff): mesh admission validates once per digest with the tamper refusal, and the concurrent refresh is unchanged. The full branch diff is now onlysnapshot.rs+source.rs. - The third commit, "Redraw the viewport only when it changes" (
e39a54f), was dropped in the rebase and exists nowhere on master (viewport_dirtyis absent from the mergedapp.rs). Dropping it may well be right — it conflicts with the since-merged visual-fixes frame loop and may deserve its own PR — but the PR title still says "redraw on change" and the description still promises "Three commits, verbatim ... rebased onto 73c3597". The description now describes a branch that does not exist.
The inline finding asks to reconcile the metadata (or restore the commit); the carried code itself needs nothing further.
|
Resolved — the branch is rebased onto current 🤖 Generated with Claude Code |
axisrow
left a comment
There was a problem hiding this comment.
Verdict: approved
Fresh run after the metadata fix; the branch is unchanged (a0728dc), and the required change is done:
- The title now names the two-commit scope — "bound shared mesh admission once, concurrent refresh queries" — with no redraw-on-change promise.
- The description documents the two commits and carries an honest "Why the fork third commit is not here" section: the merged #114 reload already avoids scene re-uploads and camera churn on unchanged framing (
needs_refit), and a future redraw gate, if profiling ever justifies one, is a new change on this base rather than a cherry-pick.
The carried code is the previously approved content, verified by range-diff in the earlier pass: mesh admission validates and bounds shared mesh content once per distinct digest with the reuse-path tamper refusal (crates/engine/src/query/snapshot.rs), and the two refresh queries run concurrently under thread::scope with panicked workers mapped to typed errors (apps/beamcraft-ui/src/source.rs). No inline findings.
Optional note, not required: the description says the render loop repaints on input rather than continuously, but the merged #114 UI still ends each frame with an unconditional ui.ctx().request_repaint(), so frames currently do run continuously; the future redraw-gate change may want to start from that line.
|
Implements the shared-mesh and refresh-query parts of #134 (mirror of axisrow#26); the redraw-gating commit was not needed after #114 removed the wasted redraws. |
What this changes
Mirror of the fork's #39 (
axisrow/BeamCraft), rebased onto upstreammaster. Two commits,verbatim (both merged cleanly on top of the merged V06.1 + visual-fixes UI):
297067f): the view snapshotadmission validates and bounds shared mesh content once per mesh instead of per reference,
so a scene that repeats one mesh N times costs one validation pass, not N.
a7e2865): the UI reload's two read queries runconcurrently instead of serially, halving the refresh wait on the read path.
No behavioural change beyond the performance profiles; read-only paths only.
Why the fork's third commit is not here
The fork's #39 also gated viewport redraws behind a
viewport_dirtyflag. Upstream needs nosuch gate: the merged #114 reload already keeps the last rendered frame when nothing changed
(
needs_refitkeeps the camera, the scene is only re-uploaded when it actually changed), andthe render loop repaints on input rather than continuously, so there is no wasted-redraw path
left for the flag to gate. If profiling later shows a repaint worth gating, that is a new
change on this base, not a cherry-pick.
How you verified it
cargo clippy -p beamcraft-ui -p beamcraft-engine --all-targets -- -D warningscargo test -p beamcraft-uiandcargo test -p beamcraft-engine --lib— 0 failed onmacOS
Provenance (clean-room)
🤖 Generated with Claude Code
Issue tracking
Fixes #351