Visitar URL original
Improve workflow compilation performance by cookingwithvlad-del · Pull Request #1106 · tt-a1i/archify · GitHub
Skip to content

Improve workflow compilation performance - #1106

Open
cookingwithvlad-del wants to merge 1 commit into
tt-a1i:devfrom
cookingwithvlad-del:perf/workflow-node-step-index
Open

cookingwithvlad-del wants to merge 1 commit into
tt-a1i:devfrom
cookingwithvlad-del:perf/workflow-node-step-index

Conversation

@cookingwithvlad-del

Copy link
Copy Markdown

Problem and value

  • Related issue / discussion: none; selected from a focused performance inspection.
  • laneTop() recomputed preceding lane heights with slice().reduce() on every lookup, and nodeStep() used findIndex() for each node outside mainPath. Both repeat work as workflow size grows. This PR precomputes lane tops and first-occurrence node indexes once per compile.
  • Before/after evidence: paired, alternating base 10b4dd5c and candidate 3233ebcd runs on Node v24.22.1 with a synthetic 2,000-lane/2,000-node workflow (10 samples per revision). Median compile time was 30.14 ms → 11.90 ms; p90 was 47.72 ms → 14.51 ms. Both produced a 2,323,000-byte SVG with the same SHA-256 (6a93f25dbc5c4cb5ffc9641362329333eec26fb96817b2dcf79bfb9e28c03631). This is a stress-case measurement, not a claim about typical workflows.

AI assistance and accountability

  • AI use: investigation, implementation, benchmark, and tests.
  • Tools and model (if known): Copilot App (Auto mode; concrete model not identified), git, Node.js.
  • Accountable contributor: @cookingwithvlad-del
  • Problem origin: code inspection and a synthetic compiler benchmark.
  • I reviewed the submitted changes and explanation, understand their impact, and can answer questions about them.

Stability impact

  • Impact class: shared workflow compiler geometry/indexing; applies to workflow compilation.
  • Existing behavior preserved: lane-top prefix arithmetic and first matching node index are retained; the stress fixture's emitted SVG is byte-identical. No schema, layout, or authored behavior is intentionally changed.
  • Real-repository generation matrix: not run. This is an output-preserving compiler optimization with no intended change to agent authoring, repair, or diagram quality; the direct compiler benchmark and existing workflow behavior tests are the relevant evidence.

Tests run

  • Base: origin/dev at 10b4dd5c; candidate: 3233ebcd.
  • npm run test:focus -- test/workflow-compiler.test.mjs test/workflow-compiler-call-contract.test.mjs test/workflow-compiler-hard-contract.test.mjs test/workflow-automatic-width.test.mjs test/workflow-counterflow-spacing.test.mjs — passed, 165 tests.
  • git diff --check — passed.
  • Synthetic paired benchmark and output digest comparison — details above; no browser or perceptual review was needed because rendered bytes are unchanged.

Ten performance improvement candidates identified

  1. Selected in this PR: cache workflow lane tops and node indexes instead of repeatedly reducing lane prefixes and searching all nodes.
  2. Build workflow group/phase lookup structures for nodeContext() instead of scanning both collections for every node (workflow-compiler.mjs, createWorkflowLaneGeometry).
  3. Reuse workflow edge-index maps where code repeatedly calls workflow.edges.indexOf() while assembling route/label diagnostics (workflow-compiler.mjs).
  4. Build a reverse workflow source-index-to-edge lookup for the routeFirst pass instead of calling workflow.edges.find() (workflow-compiler.mjs, validateReadablePinnedGeometry).
  5. Index authored workflow nodes for the repeated document.nodes.find() calls used while probing capacity repairs (workflow-compiler.mjs, createLegacyCapacityRepair).
  6. Replace the shared legend's nested legend-rectangle/obstacle scans with a spatial candidate lookup (shared/legend.mjs, collision placement).
  7. Build dataflow node-to-incident-flow adjacency once rather than filtering all flows for every node (dataflow-compiler.mjs, Showcase automatic layout).
  8. Precompute dataflow flow indexes instead of repeatedly calling indexOf() while building route candidates (dataflow-compiler.mjs, label routing).
  9. Index dataflow label rectangles by relation/index instead of repeated find()/findIndex() scans during label repair (dataflow-compiler.mjs).
  10. Index previously placed waterfall rows by node ID instead of searching placed for every parent (waterfall/render-waterfall.mjs).

Items 2–10 are inspection candidates, not individually benchmarked or included in this change.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: tt-a1i/archify
  • Branch: dev
  • File: .coderabbit.yaml
  • Commit: 10b4dd5
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cc60a71b-8c08-4c5e-947b-e46975a59880
Commits

Reviewing files that changed from the base of the PR and between 10b4dd5 and 3233ebc.

Files selected for processing: 1
  • archify/renderers/workflow/workflow-compiler.mjs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Summary

Compared base 10b4dd5 with head 3233ebc, the compiler now precomputes lane tops and first-occurrence node indexes. This avoids repeated lane-prefix reductions and node searches while preserving lane-top arithmetic and first-match behavior; no schema or authored-behavior change is reported.

At the change’s revision, the author reported 165 focused tests passing, git diff --check passing, and a synthetic benchmark improvement from 30.14 ms to 11.90 ms median. SVG output matched by size and SHA-256. These results are author-reported, not independently verified here. No CI result was supplied for the checked revision. Real-repository generation was not run.

The workflow compiler now precomputes lane top positions and caches the main-path array and node-ID indexes. Lane geometry and step calculations use these cached values.

Priority: Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Merge Risk: Minimal · up to 3233e

The optimization preserves supported workflow layout and rendering behavior.

Pre-merge checks: Passed 1 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Validation Evidence Warning Concrete coverage gap: the evaluated range is base 10b4dd5c5f2264baa315ee65a9b4cc23c13ea5f0 to head 3233ebcd7100bec64fb6450ed6345c78ee80153a. The diff precomputes lane tops and node animation step… Add one focused regression fixture with a valid mainPath, at least one off-path node, and node/edge animation metadata. Assert that main-path steps and first off-path indexes match the previous behavior. Run that focused suite at head `32…
Passed Passed checks: 1 passed
Check name Status Explanation
Contribution Scope Passed The PR states a concrete user problem: repeated lane-prefix reductions and node searches during workflow compilation. It delivers one focused performance slice in one compiler file, with no schema, la…
Full details: Contribution Scope

Explanation

The PR states a concrete user problem: repeated lane-prefix reductions and node searches during workflow compilation. It delivers one focused performance slice in one compiler file, with no schema, layout, or authored-behavior change. It records compatibility evidence through byte-identical SVG output and focused tests. No migration or rollback procedure is applicable because the change adds no contract, default, rollout, or new failure path. The synthetic benchmark is an appropriate concrete reproduction for this narrow optimization.

Full details: Validation Evidence

Explanation

Concrete coverage gap: the evaluated range is base 10b4dd5c5f2264baa315ee65a9b4cc23c13ea5f0 to head 3233ebcd7100bec64fb6450ed6345c78ee80153a. The diff precomputes lane tops and node animation steps in workflow-compiler.mjs. The author reports 165 focused tests passed and a paired synthetic benchmark with identical SVG digests. The focused suites contain multi-lane geometry coverage, but none compiles a valid mainPath; their only mainPath case tests an invalid repair reference. Therefore, the changed nodeStep() path that assigns animation steps for main-path nodes is not directly covered. Browser and perceptual evidence are not required because no generated files changed and the reported artifact bytes are identical.

Resolution

Add one focused regression fixture with a valid mainPath, at least one off-path node, and node/edge animation metadata. Assert that main-path steps and first off-path indexes match the previous behavior. Run that focused suite at head 3233ebcd7100bec64fb6450ed6345c78ee80153; the contributor owns this check. If the synthetic benchmark already includes a valid mainPath, document that input and result instead.

Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@BlueboxC

Copy link
Copy Markdown

Adapted the lane/step indexing from 3233ebcd into our customized 3.2.0 fork: implementation and tests.

Added a rendered-SVG regression with a valid main path, an off-path node and edge/node animation metadata. It checks steps 0/1 for the path, 4 for the off-path node, and 0 for the path edge. Sixteen complete before/after compiler results matched, covering both quality profiles, maintained examples, unknown lanes, duplicate nodes and empty lanes.

Independent synthetic measurement on Node 22.23.2/macOS arm64: 2,000 lanes and 2,000 nodes, two warmups and ten alternating measured samples per revision. Median compilation was 36.09 ms → 10.45 ms, with identical complete output hashes. This measures the stress fixture only.

Validation on our adapted fork: 175 focused tests; 3,481 general passes with 134 conditional skips; 315 Chrome passes with 10 skips; 56 final packaging checks. The installed package matches all 215 managed files, and Node 22/26 compiler/CLI and previous-customization probes pass. The retained MIT base and the adapted portions’ Apache-2.0 license/NOTICE are preserved.

BlueboxC

@tt-a1i tt-a1i left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-assisted review at 3233ebcd7100bec64fb6450ed6345c78ee80153a, compared with dev e837dc4. Source and supplied evidence inspected; no local test rerun in this pass.

Thanks for the measured comparison. The narrow scope is worthwhile: precompute lane prefixes and first-occurrence node indexes while preserving existing arithmetic, duplicate-ID handling and animation steps. Scope agreed for this slice; the other nine inspection candidates are outside it. The implementation retains those semantics on inspection, and the stress timing/output digest plus existing focused checks are proportionate evidence. No five-diagram authoring benchmark is required for this result-preserving optimization. Please integrate current dev, retain the original history, refresh the canonical package and let the relevant CI finish; the current zip-freshness failure must be cleared before final acceptance. BlueboxC’s additional equivalence/mainPath results are corroboration from its adapted fork, not a claim that upstream ran them. Keep the stress-only timing qualification and contributor accountability explicit.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants