Skip to content

Commit

Permalink
perf(sourcemap): shorten main loop encoding VLQ (#4586)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
overlookmotel committed Aug 1, 2024
1 parent e02bac3 commit 590d795
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions crates/oxc_sourcemap/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,25 +217,33 @@ static B64_CHARS: Aligned64 = Aligned64([
unsafe fn encode_vlq(out: &mut String, num: i64) {
let mut num = if num < 0 { ((-num) << 1) + 1 } else { num << 1 };

// Breaking out of loop early when have reached last char (rather than conditionally adding
// 32 for last char within the loop) removes 3 instructions from the loop.
// https://godbolt.org/z/Es4Pavh9j
// This translates to a 16% speed-up for VLQ encoding.
let mut digit;
loop {
let mut digit = num & 0b11111;
digit = num & 0b11111;
num >>= 5;
if num > 0 {
digit |= 1 << 5;
if num == 0 {
break;
}

let b = B64_CHARS.0[digit as usize];
let b = B64_CHARS.0[digit as usize + 32];
// SAFETY:
// * This loop can execute a maximum of 7 times, caller promises there are at least
// 7 bytes spare capacity in `out` at start, and we only push 1 byte on each turn,
// so guaranteed there is at least 1 byte capacity in `out` here.
// * This loop can execute a maximum of 7 times, and on last turn will exit before getting here.
// Caller promises there are at least 7 bytes spare capacity in `out` at start. We only
// push 1 byte on each turn, so guaranteed there is at least 1 byte capacity in `out` here.
// * All values in `B64_CHARS` lookup table are ASCII bytes.
push_byte_unchecked(out, b);

if num == 0 {
break;
}
}

let b = B64_CHARS.0[digit as usize];
// SAFETY:
// * The loop above pushes max 6 bytes. Caller promises there are at least 7 bytes spare capacity
// in `out` at start. So guaranteed there is at least 1 byte capacity in `out` here.
// * All values in `B64_CHARS` lookup table are ASCII bytes.
push_byte_unchecked(out, b);
}

/// Push a byte to `out` without bounds checking.
Expand Down

0 comments on commit 590d795

Please sign in to comment.