You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.
Here's my analysis of why this PR improves performance, based on CodSpeed flamegraph data comparing main and this branch:
Why this PR is faster
I compared the CodSpeed flamegraphs for the es/codegen/large benchmark between main (645.1 µs) and this PR (555.6 µs, +16.11% efficiency). Three optimizations are responsible for the gains:
1. Elimination of the srcmap_done HashSet (~23.5 µs saved, ~3.6% of total)
This is the single largest contributor to the speedup. On main, every source-map entry goes through JsWriter::srcmap(), which maintains a HashSet<(BytePos, u32, u32), FxBuildHasher> to deduplicate mappings. The flamegraph shows:
srcmap(): 12.3 µs self time (1.90%), 23.5 µs total (3.64%)
hashbrown::RawTable::reserve_rehash: 10.1 µs self time (1.57%) — pure hashing and rehashing overhead
On the PR branch, srcmap() and all hashbrown operations are completely absent from the flamegraph. The global HashSet was replaced with a lighter per-generated-position dedup, avoiding hashing, bucket management, and repeated heap allocations on every source-map call.
2. Indentation cache (reduced write calls)
On main, write_indent_string() loops N times (once per indent level), issuing a separate raw_write(indent_str) call each iteration. The PR introduces an indent_cache that pre-computes the full indentation string, collapsing N write calls into one. This primarily benefits the pretty-print path and is more impactful on deeply nested code like the large benchmark.
The Expr::emit_with call tree — the core recursive codegen loop — dropped from 366.2 µs (56.76%) on main to 283.9 µs (51.10%) on the PR. The write methods (write_punct, write_keyword, write_symbol) no longer route through the srcmap() function on every invocation. For example, write_punct total time dropped from 11.4 µs → 7.1 µs as it now only calls update_pos without the srcmap dedup overhead.
Why the improvement is larger on large (~16%) vs colors (~6%)
The large benchmark has many more AST nodes and source-map entries, so the HashSet overhead (which grows with the number of entries — rehashing, allocations) dominated more of the total time. The colors benchmark is small enough that the fixed costs (parsing, sourcemap finalization) dilute the per-node savings.
Summary
Warming up the performance wizard...
Analyzing performance improvements — Flamegraph analysis complete — identified three key optimizations driving the speedup
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
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.
Description:
This PR improves
swc_ecma_codegenperformance in theJsWriterhot path without changing benchmark definitions or test fixtures.Changes:
HashSet<(BytePos, line, col)>source-map dedupe with per-generated-position dedupeindent_cache) and write it in one call instead of per-level loopswrite()hot-path branching forSome(span)vsNoneMotivation:
Benchmark evidence (
cargo bench -p swc_ecma_codegen --bench bench -- --warm-up-time 1 --measurement-time 2 --baseline pre_opt):es/codegen/colors:change: [-14.707% -14.454% -14.172%]es/codegen/large:change: [-22.255% -21.769% -21.330%]No benchmark files or tests were modified.
BREAKING CHANGE:
None.
Related issue (if exists):
None.
Validation run:
git submodule update --init --recursivecargo fmt --allcargo clippy --all --all-targets -- -D warningscargo test -p swc_ecma_codegen