Repository navigation
perf(frontend): pre-index incoming edges in digital simulation solver - #21
Merged
Merged
Conversation
runSimulation re-filtered and re-sorted the full edge list for every node on every relaxation pass (O(nodes x edges x passes)). Build a per-target edge index once per call, sorted once by targetHandle with the same comparator, so evaluation order and results are unchanged. Median ms per call, synthetic ripple-carry adders (jest/jsdom, nice): runSimulation 8-bit (66n/89e) 0.094 -> 0.03 (2.8x) runSimulation 32-bit (258n/353e) 0.848 -> 0.15 (5.6x) runSimulation 128-bit (1026n/1409e) 10.3 -> 1.1-1.4 (8.3x) runSimulation 128-bit, reverse order 299 -> 9.0-9.7 (32x) simulate() 128-bit 12.8 -> 2.0-2.8 (5.4x) simulate() 128-bit, reverse order 367 -> 9.7-10.0 (37x) simulate() output is byte-identical to baseline on all benchmark circuits. Adds tests for handle-ordered inputs and adder correctness.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
✅ Deploy Preview for digisim ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
The ask: "See if this is applicable to us for any of the projects that we have made" and "use claude for it and do it for every repo". This task is that check for the DigiSim repo, using these engineering guidelines that were pasted with the ask:
DATA-ORIENTED DESIGN AND PERFORMANCE ENGINEERING. Prioritize data-oriented design, memory efficiency, cache locality and predictable performance; do not blindly preserve existing data structures; evaluate whether the current representation fits the actual access patterns and workload. Memory layout: prefer contiguous layouts over pointer-heavy structures where appropriate; consider flat arrays instead of hash tables, linked lists and trees; prefer integer indices or handles over raw pointers; consider SoA instead of AoS (and AoSoA) when workloads process single fields across many elements; inline-capacity containers for small collections; bitsets or packed representations for dense flags; bit packing when it really cuts memory or bandwidth. Performance: optimize algorithms and data layouts before adding caches; do not add caches without understanding invalidation, synchronization and memory overhead; do not remove existing caches without showing they are unnecessary or harmful; minimize allocations, copies, indirection and fragmentation; mind cache-line use, memory bandwidth, branch prediction and SIMD; prefer simple predictable access patterns. Critical: do not apply mechanically; preserve correctness, API compatibility and behavior; consider real access patterns; avoid premature optimization and needless complexity; consider concurrency, ownership and lifetimes. Verification: before optimizing identify the critical paths, establish baseline benchmarks, profile CPU, allocations and cache behavior where possible; after optimizing run correctness tests and benchmark against the original (throughput, latency, memory, allocation counts), verify improvements are measurable and repeatable, and reject changes that make performance worse or add unjustified complexity. The goal is the best measurable performance through appropriate data representation; make the common path fast and design data around the most frequent operations.
How it is to be run: (1) First find the real performance-critical paths of this repo. Many projects are dominated by network, model or database waiting; where nothing is CPU or memory bound, say so and stop with a short report and no code change. (2) Where a hot path exists, write a baseline benchmark, profile, and change data layout or algorithm only if the improvement is measured and repeatable. Ship a PR only for changes that beat the baseline with correctness tests green and no API or behavior change, with before-and-after numbers (throughput, latency, memory, allocations) in the PR. Anything that does not clearly win is dropped and listed in the report with the numbers. (3) Deliver a short report: what is hot, what is not, what was changed, measured results, what was rejected and why.
What Changed
runSimulationcall, replacing repeated edge array filtering and sorting on each relaxation iteration with constant-time map lookups.digital.test.tsverifying that component input ordering respects target handles irrespective of edge insertion order and that multi-bit ripple-carry adders converge correctly across forward and reverse node dependency orders.agent_docs/simulation-engine.mdto document the one-time edge indexing optimization in the digital relaxation loop.Risk Assessment
✅ Low: The change is a well-bounded, behavior-preserving performance optimization that replaces repeated edge filtering and sorting in the relaxation loop with a one-time per-simulation incoming edge index.
Testing
Stood up DigiSim with its production web build and backend API, driving the real product live through Google Chrome via CDP. Verified real-time digital logic evaluation and carry propagation on a 4-bit ripple-carry adder, tested adversarial out-of-order pin handle routing on the canvas, validated reverse dependency convergence across all simulation test suites (28 tests passed), and measured repeatable 3.0x to 24.6x benchmark speedup with byte-identical output to baseline. Captured 12 visual evidence screenshots and detailed JSON reports in the evidence directory.
Evidence: 00_login_page.png
Evidence: 01_initial_canvas.png
Evidence: 02_examples_gallery_modal.png
Evidence: 03_ripple_adder_loaded.png
Evidence: 04_sum0_high_after_a0_toggle.png
Evidence: 05_carry_propagation_sum1_high.png
Evidence: 06_cout_high_after_a1_toggle.png
Evidence: 07_netlist_import_reverse_handles.png
Evidence: 08_canvas_loaded_reverse_handles.png
Evidence: 09_port_a_high_indicator_top.png
Evidence: 10_both_ports_high_led_active.png
Evidence: 11_port_b_high_indicator_bottom.png
Evidence: live_interaction_evidence.json
JSON recording live browser DOM states and verification results across ripple adder switch toggles.Evidence: adversarial_reverse_handles_evidence.json
JSON recording adversarial port handle testing with reversed edge order.Evidence: performance_benchmark_results.json
JSON recording benchmark numbers comparing baseline vs optimized solver (speedup 3.0x to 24.6x).Measured before and after
Synthetic ripple-carry adders (about 8 nodes per bit). Median ms per call, jest/jsdom under
nice, 3 warm-up runs, at least 15 runs and 1.5 s per case. "rev" lists nodes in reverse dependency order (worst case for relaxation). Baseline is one run; "after" is two independent runs.Full
simulate()output for all 6 benchmark circuits is byte-identical to the baseline. Allocation counts are not reported: heap deltas were too noisy under jest (no--expose-gc); the change removes one array allocation plus one sort per node per relaxation pass.Not pursued (unmeasured or behavior-risking): event-driven worklist (evaluation order affects latch/feedback results), typed-array value storage, caching parsed
customComponentsand subcircuit clones. The analog MNA solver, switch-level solver and backend/ML paths were not benchmarked.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
cd frontend && npm test -- --watchAll=false src/logic/simulation/digital.test.tscd frontend && npm test -- --watchAll=false src/logic/simulationStand up DigiSim production build and Flask backend servicesCDP live end-to-end interactive simulation of 4-Bit Ripple Carry Full Adder from Examples GalleryCDP live adversarial netlist import with reversed edge handles asserting gate visual ports and logic levelsComparative latency and throughput benchmarking across 8-bit, 32-bit, and 128-bit ripple adder circuits✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.