Skip to content

Comments

perf(codegen): reduce allocations in SourcemapBuilder#13677

Merged
graphite-app[bot] merged 1 commit intomainfrom
09-11-perf_codegen_reduce_allocations_in_sourcemapbuilder_
Sep 11, 2025
Merged

perf(codegen): reduce allocations in SourcemapBuilder#13677
graphite-app[bot] merged 1 commit intomainfrom
09-11-perf_codegen_reduce_allocations_in_sourcemapbuilder_

Conversation

@overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented 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.

@github-actions github-actions bot added A-codegen Area - Code Generation C-performance Category - Solution not expected to change functional behavior, only performance labels Sep 11, 2025
Copy link
Member Author

overlookmotel commented Sep 11, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

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.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codspeed-hq
Copy link

codspeed-hq bot commented Sep 11, 2025

CodSpeed Instrumentation Performance Report

Merging #13677 will not alter performance

Comparing 09-11-perf_codegen_reduce_allocations_in_sourcemapbuilder_ (4ded22b) with main (239d4cb)1

Summary

✅ 37 untouched benchmarks

Footnotes

  1. No successful run was found on main (4ded22b) during the generation of this report, so 239d4cb was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@overlookmotel overlookmotel marked this pull request as ready for review September 11, 2025 07:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR optimizes memory allocation patterns in the SourcemapBuilder by reverting from mem::take back to clone with adaptive capacity management.

Key changes:

  • Replaces mem::take with clone to avoid unnecessary reallocations
  • Removes fixed capacity reservation in favor of adaptive growth
  • Adds detailed comments explaining the memory allocation optimization rationale

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@graphite-app
Copy link
Contributor

graphite-app bot commented Sep 11, 2025

Merge activity

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 graphite-app bot force-pushed the 09-11-perf_codegen_reduce_allocations_in_sourcemapbuilder_ branch from 3613afd to 4ded22b Compare September 11, 2025 07:31
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.
@graphite-app graphite-app bot merged commit 4ded22b into main Sep 11, 2025
25 checks passed
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Sep 11, 2025
@graphite-app graphite-app bot deleted the 09-11-perf_codegen_reduce_allocations_in_sourcemapbuilder_ branch September 11, 2025 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-codegen Area - Code Generation C-performance Category - Solution not expected to change functional behavior, only performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants