Skip to content

Conversation

overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented Jul 31, 2024

In oxc_sourcemap's VLQ encoding, avoid bounds checks when pushing bytes to the encoded string in the hot loop.

Those bounds checks are quite expensive as they involve a function call to alloc::raw_vec::RawVec::grow_one, and that happens on every single pushed byte.

https://godbolt.org/z/44G8jjss3

Not much difference on benchmarks, as VLQ encoding is only a small part of source map generation, but a local benchmark of just VLQ encoding shows this increases performance by 11%.

Copy link
Contributor

graphite-app bot commented Jul 31, 2024

Your org has enabled the Graphite merge queue for merging into main

Add the label “merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge. Or use the label “hotfix” to add to the merge queue as a hot fix.

You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link.

Copy link
Member Author

overlookmotel commented Jul 31, 2024

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

Join @overlookmotel and the rest of your teammates on Graphite Graphite

Copy link

codspeed-hq bot commented Jul 31, 2024

CodSpeed Performance Report

Merging #4583 will not alter performance

Comparing 07-31-perf_sourcemap_elide_bounds_checks_in_vlq_encoding (d00014e) with main (e116ae0)

Summary

✅ 32 untouched benchmarks

@overlookmotel overlookmotel force-pushed the 07-31-perf_sourcemap_elide_bounds_checks_in_vlq_encoding branch from 2cc2ae3 to 0cd2e0d Compare July 31, 2024 10:05
@overlookmotel overlookmotel marked this pull request as ready for review July 31, 2024 11:12
@overlookmotel overlookmotel force-pushed the 07-31-perf_sourcemap_elide_bounds_checks_in_vlq_encoding branch from 13ebac0 to 2fddbe2 Compare July 31, 2024 12:57
@overlookmotel overlookmotel force-pushed the 07-31-perf_sourcemap_elide_bounds_checks_in_vlq_encoding branch 4 times, most recently from 4d609bb to 18d2df4 Compare July 31, 2024 16:51
@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label Aug 1, 2024
Copy link
Contributor

graphite-app bot commented Aug 1, 2024

Merge activity

  • Aug 1, 4:33 AM EDT: The merge label 'merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Aug 1, 4:33 AM EDT: Boshen added this pull request to the Graphite merge queue.
  • Aug 1, 4:38 AM EDT: Boshen merged this pull request with the Graphite merge queue.

In `oxc_sourcemap`'s VLQ encoding, avoid bounds checks when pushing bytes to the encoded string in the hot loop.

Those bounds checks are quite expensive as they involve a function call to `alloc::raw_vec::RawVec::grow_one`, and that happens on every single pushed byte.

https://godbolt.org/z/44G8jjss3

Not much difference on benchmarks, as VLQ encoding is only a small part of source map generation, but a local benchmark of just VLQ encoding shows this increases performance by 11%.
@Boshen Boshen force-pushed the 07-31-perf_sourcemap_elide_bounds_checks_in_vlq_encoding branch from 18d2df4 to d00014e Compare August 1, 2024 08:34
@graphite-app graphite-app bot merged commit d00014e into main Aug 1, 2024
24 checks passed
@graphite-app graphite-app bot deleted the 07-31-perf_sourcemap_elide_bounds_checks_in_vlq_encoding branch August 1, 2024 08:38
@oxc-bot oxc-bot mentioned this pull request Aug 1, 2024
Boshen added a commit that referenced this pull request Aug 1, 2024
## [0.23.0] - 2024-08-01

- 27fd062 sourcemap: [**BREAKING**] Avoid passing `Result`s (#4541)
(overlookmotel)

### Features

- a558492 codegen: Implement `BinaryExpressionVisitor` (#4548) (Boshen)
- 7446e98 codegen: Align more esbuild implementations (#4510) (Boshen)
- 35654e6 codegen: Align operator precedence with esbuild (#4509)
(Boshen)
- b952942 linter: Add eslint/no-unused-vars (⭐ attempt 3.2) (#4445)
(DonIsaac)
- 85e8418 linter: Add react/jsx-curly-brace-presence (#3949) (Don Isaac)
- cf1854b semantic: Remove `ReferenceFlags::Value` from non-type-only
exports that referenced type binding (#4511) (Dunqing)

### Bug Fixes

- b58ed80 codegen: Enable more test cases (#4585) (Boshen)
- 6a94e3f codegen: Fixes for esbuild test cases (#4503) (Boshen)
- d5c4b19 parser: Fix enum member parsing (#4543) (DonIsaac)

### Performance

- 4c6d19d allocator: Use capacity hint (#4584) (Luca Bruno)
- 7585e16 linter: Remove allocations for string comparisons (#4570)
(DonIsaac)
- 55a8763 parser: Faster decoding unicode escapes in identifiers (#4579)
(overlookmotel)
- ae1d38f parser: Fast path for ASCII when checking char after numeric
literal (#4577) (overlookmotel)
- 56ae615 parser: Make not at EOF the hot path in `Source` methods
(#4576) (overlookmotel)
- 25679e6 parser: Optimize `Lexer::hex_digit` (#4572) (overlookmotel)
- bb33bcc parser: Speed up lexing non-decimal numbers (#4571)
(overlookmotel)
- ab8509e parser: Use `-` not `saturating_sub` (#4561) (overlookmotel)
- c9c38a1 parser: Support peeking over bytes (#4304) (lucab)
- 0870ee1 parser: Get and check lookahead token (#4534) (lucab)
- d00014e sourcemap: Elide bounds checks in VLQ encoding (#4583)
(overlookmotel)
- 1fd9dd0 sourcemap: Use simd to escape JSON string (#4487)
(Brooooooklyn)

### Documentation

- 0914e47 ast: Add doc comments to literal nodes (#4551) (DonIsaac)
- c6a11be ast: Auto-generate doc comments for AstBuilder methods (#4471)
(DonIsaac)

### Refactor

- e68ed62 parser: Convert lexer byte handler for `|` to a single match
(#4575) (overlookmotel)
- bba824b parser: Convert `Lexer::read_minus` to a single match (#4574)
(overlookmotel)
- ef5418a parser: Convert `Lexer::read_left_angle` to a single match
(#4573) (overlookmotel)
- 9e5be78 parser: Add `Lexer::consume_2_chars` (#4569) (overlookmotel)
- 649913e parser: Extract `u8` not `&u8` when iterating over bytes
(#4568) (overlookmotel)
- 59f00c0 parser: Rename function (#4566) (overlookmotel)
- 8e3e910 parser: Rename vars (#4565) (overlookmotel)
- 0c0601f parser: Rename function (#4564) (overlookmotel)
- 0acc4a7 parser: Fetch 2 bytes in `?` byte handler (#4563)
(overlookmotel)
- 565eccf parser: Shorten lexer code (#4562) (overlookmotel)
- 148bdb5 parser: Adjust function inlining (#4530) (overlookmotel)
- 16c7b98 semantic: Move CatchClause scope binding logic to
visit_block_statement (#4505) (Dunqing)
- d6974d4 semantic: `AstNodeParentIter` fetch nodes lazily (#4533)
(overlookmotel)
- d914b14 semantic: Reusing the same reference (#4529) (Dunqing)
- 7b5e1f5 semantic: Use `is_empty()` instead of `len() == 0` (#4532)
(overlookmotel)
- 9db4259 semantic: Inline trivial methods (#4531) (overlookmotel)
- 7c42ffc sourcemap: Align Base64 chars lookup table to cache line
(#4535) (overlookmotel)
- 96602bf transformer/typescript: Determine whether to remove
`ExportSpeicifer` by `ReferenceFlags` (#4513) (Dunqing)
- e6a8af6 traverse: Speed up tests (#4538) (overlookmotel)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
Boshen pushed a commit that referenced this pull request Aug 1, 2024
Reduce number of operations in main loop in source map VLQ encoding.

#4583 made pushing a byte to output only 2 instructions, so that makes it workable to repeat `push_byte_unchecked` inside and outside the loop.

On a local benchmark of just VLQ encoding shows this increases performance by 16% (on top of the 11% from #4583).

Probably main gain is it makes a fast path for encoding `0`, which is common.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0-merge Merge with Graphite Merge Queue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants