Skip to content

Improve the encoding scheme of vint - #15

Merged
tomtomwombat merged 5 commits into
mainfrom
tomtomwombat/vint-perf
Oct 8, 2026
Merged

tomtomwombat merged 5 commits into
mainfrom
tomtomwombat/vint-perf

Conversation

@tomtomwombat

@tomtomwombat tomtomwombat commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

PR has two changes:

  1. When comparing two heap ColdStrings, we can read and compare the first WIDTH bytes without parsing the vint. This is a fast path and works because strings are only stored on heap iff there are more than WIDTH bytes. We don't read WIDTH + 2 bytes, even though we could (accounting for at least 1 vint byte, plus WIDTH + 1 or more UTF-8 bytes) because it's slower (probably because it requires more reads?).
  2. Optimize the vint encoding scheme. I tried a bunch, but the one here is the fastest, and compact too. It's adapted from https://www.inkandswitch.com/tangents/bijou64/ with cold-string specific optimizations, because we can always read WIDTH + 2 bytes from heap, and mask away junk UTF-8 bytes past the var-int's len.

Benchmark: as_str (ns/op)

Type len=0..=4 len=0..=8 len=0..=16 len=0..=32 len=0..=255 len=4..=4 len=8..=8 len=16..=16 len=32..=32 len=255..=255
String 0.69 0.69 0.69 0.69 0.69 0.69 0.69 0.69 0.69 0.69
cold_string::ColdString 1.66 1.61 1.20 1.00 0.94 1.62 1.63 0.77 0.80 0.83
compact_str::CompactString 0.75 0.76 0.75 0.72 0.74 0.76 0.74 0.75 0.71 0.70
compact_string::CompactString 0.73 0.72 0.72 0.73 0.76 0.72 0.72 0.72 0.75 0.76
smallstr::SmallString<[u8; 8]> 0.67 0.67 0.85 0.69 0.73 0.67 0.68 0.67 0.66 0.66
smartstring::alias::String 2.43 2.43 2.43 2.32 1.49 2.43 2.43 2.43 1.33 1.34
smol_str::SmolStr 0.67 0.67 0.67 0.66 0.81 0.67 0.68 0.67 0.68 0.67

Benchmark: eq (ns/op)

Type len=4, eq=0 len=4, eq=0.5 len=4, eq=1 len=8, eq=0 len=8, eq=0.5 len=8, eq=1 len=16, eq=0 len=16, eq=0.5 len=16, eq=1 len=32, eq=0 len=32, eq=0.5 len=32, eq=1 len=255, eq=0 len=255, eq=0.5 len=255, eq=1
String 2.33 2.98 2.74 2.51 2.94 2.60 2.39 2.97 2.81 2.20 2.84 2.62 2.18 11.61 13.55
cold_string::ColdString 1.31 1.31 1.31 1.31 1.31 1.31 1.42 4.79 5.72 1.44 5.73 6.68 1.53 12.25 15.54
compact_str::CompactString 2.90 3.95 3.24 3.04 3.85 3.25 3.04 4.44 3.47 2.84 3.55 3.30 2.84 12.80 14.56
compact_string::CompactString 2.45 3.03 2.83 2.05 3.17 3.96 2.06 4.21 4.53 2.03 5.02 5.11 2.11 12.82 14.62
smallstr::SmallString<[u8; 8]> 2.45 3.25 3.03 2.81 3.03 2.81 3.04 3.87 3.47 2.83 4.56 3.26 2.87 11.99 13.97
smartstring::alias::String 6.55 7.42 6.89 6.13 7.33 7.38 6.11 9.05 7.99 4.97 6.40 5.42 4.97 13.69 14.18
smol_str::SmolStr 4.21 3.29 1.96 3.77 3.13 1.96 3.84 3.33 2.08 4.33 5.72 4.59 4.19 13.54 15.20

Benchmark: len (ns/op)

Type len=4 len=8 len=16 len=255
String 0.43 0.43 0.43 0.43
cold_string::ColdString 0.42 0.43 0.43 0.43
compact_str::CompactString 0.42 0.42 0.43 0.43
compact_string::CompactString 0.43 0.43 0.43 0.43
smallstr::SmallString<[u8; 8]> 0.43 0.42 0.42 0.43
smartstring::alias::String 1.29 1.28 1.30 1.29
smol_str::SmolStr 0.43 0.42 0.45 0.45

Benchmark: new (ns/op)

Type len=0..=4 len=0..=8 len=0..=16 len=0..=32 len=0..=255 len=4..=4 len=8..=8 len=16..=16 len=32..=32 len=255..=255
String 29.64 31.99 35.71 33.84 41.24 28.58 28.80 29.55 30.34 33.59
cold_string::ColdString 10.77 10.22 25.68 30.44 43.24 6.25 5.04 33.79 33.74 37.48
compact_str::CompactString 11.52 12.06 12.31 18.07 53.39 10.88 10.84 10.95 38.46 45.86
compact_string::CompactString 34.95 36.84 40.28 38.24 44.93 29.88 30.26 31.84 32.20 35.72
smallstr::SmallString<[u8; 8]> 9.52 10.01 22.50 29.03 41.24 4.81 2.38 29.06 31.15 33.29
smartstring::alias::String 15.60 15.82 15.66 31.46 88.72 15.67 15.65 10.89 160.37 72.01
smol_str::SmolStr 17.61 17.93 15.99 22.94 55.73 18.27 13.86 13.75 39.46 42.07

@tomtomwombat
tomtomwombat force-pushed the tomtomwombat/vint-perf branch from 62563aa to 294a106 Compare October 8, 2026 00:42
@tomtomwombat
tomtomwombat force-pushed the tomtomwombat/vint-perf branch from 294a106 to ed8efab Compare October 8, 2026 05:47
@tomtomwombat
tomtomwombat merged commit ee470a7 into main Oct 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant