perf(codegen): optimize sourcemap builder to reduce allocations#13670
Merged
graphite-app[bot] merged 1 commit intomainfrom Sep 11, 2025
Merged
perf(codegen): optimize sourcemap builder to reduce allocations#13670graphite-app[bot] merged 1 commit intomainfrom
graphite-app[bot] merged 1 commit intomainfrom
Conversation
Contributor
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. |
CodSpeed Instrumentation Performance ReportMerging #13670 will not alter performanceComparing Summary
Footnotes |
Member
Author
Merge activity
|
## Summary This PR optimizes the sourcemap builder to reduce memory allocations and improve performance. Profiling showed that `update_generated_line_and_column` and `add_source_mapping` were performance bottlenecks. ### Changes Made **Optimization 4: Optimize Line Offset Table Generation** - Pre-allocate `columns` vector with capacity 256 to avoid frequent reallocations - Replace `columns.clone().into_boxed_slice()` with `std::mem::take(&mut columns).into_boxed_slice()` to avoid unnecessary cloning - Reserve capacity after taking the vector to maintain performance for subsequent lines ### Performance Impact These changes reduce memory allocations when generating sourcemaps, especially for files with Unicode characters. The `clone()` operation was creating unnecessary copies of potentially large vectors on every Unicode line, which is now eliminated. ### Future Optimizations Additional optimizations from the analysis that could be implemented in follow-up PRs: 1. Use SIMD-accelerated line break detection with `memchr` 2. Optimize UTF-16 column calculation to avoid iterator allocation 3. Add fast path for sequential token processing 5. Inline hot functions with `#[inline(always)]` ## Test Plan - [x] All existing tests pass - [x] No functional changes, only performance optimizations - [x] Verified that sourcemap generation still works correctly 🤖 Generated with [Claude Code](https://claude.ai/code)
dd78d91 to
b35bf30
Compare
This was referenced Sep 11, 2025
graphite-app bot
pushed a commit
that referenced
this pull request
Sep 11, 2025
Follow-on after #13670. That PR made 2 changes: 1. Pre-allocating capacity in `columns` `Vec`. 2. `mem::take`-ing `columns` for each line, rather than re-using it. In my opinion, the 1st change is good, but the 2nd is not. Revert the usage of `mem::take`, and add a comment explaining why the `.clone()` is not as bad as it looks! Before this PR: `columns` will likely have spare capacity, so `mem::take(&mut columns).into_boxed_slice()` will perform a reallocation to drop the excess capacity, and then `columns.reserve(256)` performs a 2nd allocation. Approach after this PR: 1. `columns.clone().into_boxed_slice()` performs 1 allocation, and copies the data from `columns` into this new allocation. `columns.clear()` does not perform any reallocation, and is a very cheap operation. 2. `columns` `Vec` is reused over and over, and will grow adaptively depending on how heavy the file's use of unicode chars is, rather than always going back to estimated max capacity of 256. Benchmarks show a very small positive difference.
graphite-app bot
pushed a commit
that referenced
this pull request
Sep 11, 2025
#13670 optimized `SourcemapBuilder` to pre-reserve capacity in `columns` `Vec`. However, after #13677, `columns` will resize adaptively depending on how many unicode chars in source text. So now initial capacity of 256 (1 KiB) is probably excessive for most cases. Reduce it to 16 (64 bytes, which is 1 x CPU cache line). Codspeed shows little change in perf (max +0.1%, min -0.1%), and memory usage will definitely be reduced.
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
This PR optimizes the sourcemap builder to reduce memory allocations and improve performance. Profiling showed that
update_generated_line_and_columnandadd_source_mappingwere performance bottlenecks.Changes Made
Optimization 4: Optimize Line Offset Table Generation
columnsvector with capacity 256 to avoid frequent reallocationscolumns.clone().into_boxed_slice()withstd::mem::take(&mut columns).into_boxed_slice()to avoid unnecessary cloningPerformance Impact
These changes reduce memory allocations when generating sourcemaps, especially for files with Unicode characters. The
clone()operation was creating unnecessary copies of potentially large vectors on every Unicode line, which is now eliminated.Future Optimizations
Additional optimizations from the analysis that could be implemented in follow-up PRs:
memchr#[inline(always)]Test Plan
🤖 Generated with Claude Code