mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
perf(sourcemap): shorten main loop encoding VLQ (#4586)
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.
This commit is contained in:
parent
e02bac357a
commit
590d79530e
1 changed files with 21 additions and 13 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
let b = B64_CHARS.0[digit as usize];
|
||||
// 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.
|
||||
// * 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 + 32];
|
||||
// SAFETY:
|
||||
// * 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);
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue