Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(sourcemap): improve perf of search_original_line_and_column #7926

Conversation

camc314
Copy link
Contributor

@camc314 camc314 commented Dec 15, 2024

this seems to show a decent speed up on perf.
the thinking behind this change is:

  1. subsequent calls to search_original_line_and_column will never look at back at lines it has already searched
  2. binary search is faster in this case as typically idx is only increased by a small amount

Given this, we can skip checking a bunch of lines (that will never return true) improving performance.

This is a very hot path.

$ hyperfine --warmup=3 ./target/release-with-debug/examples/sourcemap-main ./target/release-with-debug/examples/sourcemap
Benchmark 1: ./target/release-with-debug/examples/sourcemap-main
  Time (mean ± σ):      79.5 ms ±   5.5 ms    [User: 65.1 ms, System: 12.2 ms]
  Range (min … max):    76.8 ms … 111.7 ms    37 runs
 
  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.
 
Benchmark 2: ./target/release-with-debug/examples/sourcemap
  Time (mean ± σ):      72.9 ms ±   0.9 ms    [User: 59.2 ms, System: 12.2 ms]
  Range (min … max):    70.6 ms …  75.0 ms    40 runs
 
Summary
  ./target/release-with-debug/examples/sourcemap ran
    1.09 ± 0.08 times faster than ./target/release-with-debug/examples/sourcemap-main

@github-actions github-actions bot added A-codegen Area - Code Generation C-performance Category - Solution not expected to change functional behavior, only performance labels Dec 15, 2024
Copy link
Contributor Author

camc314 commented Dec 15, 2024


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.

@camc314 camc314 marked this pull request as ready for review December 15, 2024 23:53
Copy link

codspeed-hq bot commented Dec 15, 2024

CodSpeed Performance Report

Merging #7926 will improve performances by 8.93%

Comparing c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ (d9b6e31) with main (ff9d1b3)

Summary

⚡ 1 improvements
✅ 28 untouched benchmarks

Benchmarks breakdown

Benchmark main c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ Change
codegen_sourcemap[checker.ts] 74.4 ms 68.3 ms +8.93%

@camc314 camc314 force-pushed the c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ branch from c123b76 to 2a514a2 Compare December 16, 2024 00:01
@camc314
Copy link
Contributor Author

camc314 commented Dec 16, 2024

there's the op for more perf gains here.

SourceMapBuilder::tokens is just a Vec with no initial size. we can probably guess the size based on the length of the text to avoid some allocations - even a rough guess should be ok.

poc:


Summary
  ./target/release-with-debug/examples/sourcemap ran # reserving vec capacity
    1.03 ± 0.04 times faster than ./target/release-with-debug/examples/sourcemap-with-opt1 # this PR 
    1.11 ± 0.05 times faster than ./target/release-with-debug/examples/sourcemap-main  # buiilt against main

https://github.com/oxc-project/oxc-sourcemap/blob/0e5ec37a00d6c563727814b9ec41232b226eff90/src/sourcemap_builder.rs#L19

Copy link
Contributor

@overlookmotel overlookmotel left a comment

Choose a reason for hiding this comment

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

Very nice!

Did I write this code?? It looks familiar. It also looks embarrassingly messy! I'd probably write it differently if I wrote it today. I think I've got a bit better at coding over past 6 months...

If you've enjoyed this and you'd be interested in pushing for further gains, I have a few thoughts of other optimizations we might be able to make, which I guess I didn't see first time around.

crates/oxc_codegen/src/sourcemap_builder.rs Outdated Show resolved Hide resolved
crates/oxc_codegen/src/sourcemap_builder.rs Outdated Show resolved Hide resolved
@camc314 camc314 force-pushed the c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ branch 4 times, most recently from 39a63e8 to 6699dc2 Compare December 16, 2024 11:01
@camc314 camc314 changed the base branch from main to c/12-16-refactor_benchmark_transform_code_before_codegen December 16, 2024 11:01
@camc314
Copy link
Contributor Author

camc314 commented Dec 16, 2024

Very nice!

Did I write this code?? It looks familiar. It also looks embarrassingly messy! I'd probably write it differently if I wrote it today. I think I've got a bit better at coding over past 6 months...

yes and no i think? i think @ underfin wrote this originally, then you made some perf improvements in #4641

If you've enjoyed this and you'd be interested in pushing for further gains, I have a few thoughts of other optimizations we might be able to make, which I guess I didn't see first time around.

👀 let me know what you can see

@camc314 camc314 force-pushed the c/12-16-refactor_benchmark_transform_code_before_codegen branch 2 times, most recently from 948da44 to f9f88b2 Compare December 16, 2024 12:49
@Boshen Boshen changed the base branch from c/12-16-refactor_benchmark_transform_code_before_codegen to graphite-base/7926 December 16, 2024 13:08
Boshen pushed a commit that referenced this pull request Dec 16, 2024
@overlookmotel
Copy link
Contributor

👀 let me know what you can see

I'll open an issue once we have this PR merged.

@camc314 camc314 force-pushed the c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ branch from 32da65c to 6312922 Compare December 16, 2024 14:11
@camc314 camc314 requested a review from Dunqing as a code owner December 16, 2024 14:11
@camc314 camc314 changed the base branch from graphite-base/7926 to main December 16, 2024 14:12
@github-actions github-actions bot added the A-transformer Area - Transformer / Transpiler label Dec 16, 2024
@nrayburn-tech
Copy link
Contributor

Unrelated to this PR, but I just want to say that the conversations you two have in your PRs/issues are super helpful to somebody unfamiliar with Rust (or any low level languages).

Thanks for the explanations @overlookmotel and @camc314 for always asking questions.

@camc314
Copy link
Contributor Author

camc314 commented Dec 16, 2024

Unrelated to this PR, but I just want to say that the conversations you two have in your PRs/issues are super helpful to somebody unfamiliar with Rust (or any low level languages).

Thanks for the explanations @overlookmotel and @camc314 for always asking questions.

❤️ this is amazing to hear. overlookmotel always has the answers

now just to make rust a part of my day job 🙂

@Boshen Boshen requested a review from overlookmotel December 17, 2024 02:27
@overlookmotel overlookmotel force-pushed the c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ branch from 542c552 to ca823b9 Compare December 17, 2024 10:47
@overlookmotel
Copy link
Contributor

overlookmotel commented Dec 17, 2024

@camc314 I hope you don't mind, but I thought I'd give it a go. I've pushed another commit with an optimized implementation of search_original_line_forwards.

I didn't want to use #[cold], but I couldn't find another way to get the assembly in the shape I wanted - fastest path for "on the same line as last time", followed by the unrolled loop covering next 16 lines.

https://godbolt.org/z/heh1cnYa4 (the unrolled loop is the part where same 3 lines repeat over and over, .LBB0_3 is start of the binary search).

Let's see what CodSpeed says!

(We could get rid of the cold path by adding 16 dummy entries to end of the Vec<Line> in generate_line_offset_tables, so there are always at least 16 lines to search over. I'm not sure if that's a good idea or not.)

@overlookmotel
Copy link
Contributor

OK, the perf gain is back to where it was originally, and we don't have the problem of pathologically bad perf if code has moved a long distance any more.

If you think my code looks OK, would you like to apply the same scheme to the backwards search?

@Boshen Boshen merged commit 78d2e83 into main Dec 23, 2024
27 checks passed
@Boshen Boshen deleted the c/12-15-perf_sourcemap_improve_perf_of_search_original_line_and_column_ branch December 23, 2024 06:51
Boshen added a commit that referenced this pull request Dec 25, 2024
## [0.44.0] - 2024-12-25

- ad2a620 ast: [**BREAKING**] Add missing
`AssignmentTargetProperty::computed` (#8097) (Boshen)

### Features

- c2daa20 ast: Add `Expression::into_inner_expression` (#8048)
(overlookmotel)
- 618b6aa codege: Minify whitespace in object getter / setter (#8080)
(Boshen)
- 4727667 codegen: Minify arrow expr `(x) => y` -> `x => y` (#8078)
(Boshen)
- 0562830 codegen: Minify string with backtick when needed (#8095)
(Boshen)
- 6237c05 codegen: Minify more whitespace (#8089) (Boshen)
- 6355b7c codegen: Minify `export { 's' as 's' }` -> `export { 's' }`
(#8093) (Boshen)
- fccfda9 codegen: Minify `class{static[computed]}` (#8088) (Boshen)
- f873139 codegen: Minify `for (_ of [])` -> `for(_ of[])` (#8086)
(Boshen)
- 8b8cbcd codegen: Minify `case "foo"` -> `case"foo"` (#8085) (Boshen)
- 414c118 codegen: Minify `yield "s"` -> `yield"s"` (#8084) (Boshen)
- f8f067b codegen: Minify class method `async*fn(){}` (#8083) (Boshen)
- 1d5ae81 codegen: Minify `const [foo] = bar` -> `const[foo]=bar`
(#8079) (Boshen)
- e3f78fb codegen: `new Foo()` -> `new Foo` when minify (#8077) (Boshen)
- d84d60a codegen: Minify numbers with large exponents (#8074) (Boshen)
- 373279b codegen: Balance string quotes when minify whitespace (#8072)
(Boshen)
- 5397fe9 minifier: Constant fold `undefined?.bar` -> `undefined`
(#8075) (Boshen)
- 1932f1e minifier: Fold `foo === undefined || foo === null` (#8063) (翠
/ green)
- 11c4bd8 span: Implement source type `{file basename}.d.{extension}.ts`
(#8109) (Boshen)
- be4feb4 syntax: Add `SymbolId::new` method (#8041) (overlookmotel)
- e632a7b transformer: Remove typescript symbols after transform (#8069)
(Boshen)

### Bug Fixes

- bdc241d codegen: Disallow template literals in object property key
(#8108) (Boshen)
- 728ed20 codegen: Print `yield * ident` correctly (Boshen)
- b605baa minifier: Constant fold strings with tab char (#8096) (Boshen)
- de82492 parser: Report syntax errors for missing constructor
implementations (#8081) (camc314)
- 55d6eb9 parser: Disallow type parameters on class constructors (#8071)
(injuly)
- be2c60d parser: Parse `import source from from 'mod'` (#8056) (Boshen)
- 708e9cf semantic: Report errors for missing class method impls (#8082)
(camc314)
- 3057686 transformer/class-properties: Unwrap parenthesised expressions
(#8049) (overlookmotel)
- e67cd05 transformer/class-properties: Correctly resolve private fields
pointing to private accessors (#8047) (overlookmotel)
- 6b08c6e transformer/class-properties: Correctly resolve private fields
pointing to private methods (#8042) (overlookmotel)
- 274f117 transformer/nullish-coalescing: Use correct scope id for
binding (#8053) (camc314)

### Performance

- 78d2e83 sourcemap: Improve perf of `search_original_line_and_column`
(#7926) (Cameron)

### Refactor

- 7110c7b codegen: Add `print_quoted_utf16` and `print_unquoted_utf16`
methods (#8107) (Boshen)
- 8b54d89 minifier: Remove parens must happen on enter (#8060) (Boshen)
- 7cb84f3 minifier: Only minify on ast node exit (#8059) (Boshen)
- 77d845a minifier: Fuse DCE AST passes (#8058) (Boshen)
- 6123f5e minifier: Fold statements on exit (#8057) (Boshen)
- cbd5169 transformer/class-properties: Do not recreate private field if
not transforming it (#8044) (overlookmotel)
- 98e8a72 transformer/class-properties: Do not take mut ref when immut
ref will do (#8040) (overlookmotel)

Co-authored-by: Boshen <[email protected]>
Boshen pushed a commit that referenced this pull request Dec 31, 2024
…tract with overflow in `search_original_line_and_column` (#8185)

See:
https://github.com/oxc-project/monitor-oxc/actions/runs/12531534720/job/34949348092
Related: #7926 

This line causes panic.

https://github.com/oxc-project/oxc/blob/46fc1a8b7d26f1971d1809d68060cb0259dc4b53/crates/oxc_codegen/src/sourcemap_builder.rs#L147-L148

After investigation, I found that the root cause was the code removed
in this PR. I don’t understand what the code was used for, but it was
obviously wrong. Because `idx` is always smaller than `cap`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area - Code Generation A-transformer Area - Transformer / Transpiler 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.

4 participants