perf: fix O(n²) bottlenecks in simplification and YAML serialization#307
Merged
perf: fix O(n²) bottlenecks in simplification and YAML serialization#307
Conversation
Profiles simplifyRawFigmaObject + serialization, reporting wall time, memory usage, node counts, and output size. Supports --profile flag for CPU profiling via Chrome DevTools.
Shows cumulative time and percentage for each extractor, afterChildren, and walk/yield overhead. Also addresses review feedback: consolidate imports through barrel, remove section-divider comments, fix RSS label.
Replace O(n) linear scan with JSON.stringify on both sides per lookup with a Map-based reverse cache (serialized value → varId). The cache is scoped per GlobalVars instance via WeakMap, so it's automatically tied to each extraction run. On a 71.6 MB / 30k node file: 107s → 139ms for simplification.
Verifies that two nodes with identical fills reference the same global variable, ensuring the cache-based deduplication produces correct results.
- noRefs: true — skip O(n²) reference detection (no shared refs in output) - lineWidth: -1 — skip line-folding regex (output goes to LLMs) - noCompatMode: true — skip YAML 1.0/1.1 compat checks per string - schema: JSON_SCHEMA — fewer implicit type resolvers per string
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.
Summary
Profiled the
simplifyRawFigmaObjectpipeline and fixed two independent O(n²) performance bottlenecks, then added tooling to catch future regressions.1. Style lookup cache
findOrCreateVarwas doing an O(n) linear scan withJSON.stringifyon both sides for every style lookup — effectively O(n²) across all nodes. Replaced with aWeakMap-based reverse cache for O(1) lookups.2. YAML serialization options
js-yaml's
dump()defaults include O(n²) reference detection, line-folding regex, and legacy compat checks. Since our output goes to LLMs, not human editors, we disable all of these.The speedup scales superlinearly with file size because both bottlenecks were O(n²).
3. Benchmark script
Added
scripts/benchmark-simplify.ts(pnpm benchmark:simplify) that reports:--profileflag for CPU profiling via Chrome DevToolsOther changes
SimplifiedNodefrom the extractors barrel (src/extractors/index.ts)Test plan