Skip to content

perf: Int::decode small-value fast path#717

Merged
lwshang merged 2 commits intomasterfrom
sat-perf-int-decode
Mar 15, 2026
Merged

perf: Int::decode small-value fast path#717
lwshang merged 2 commits intomasterfrom
sat-perf-int-decode

Conversation

@sasa-tomic
Copy link
Copy Markdown
Member

@sasa-tomic sasa-tomic commented Mar 13, 2026

Summary

Decode SLEB128-encoded Int values into i64 first, only falling back to BigInt for values that exceed 64-bit range. Mirrors the existing Nat::decode fast path from an earlier commit in this series.

  • Fast path: accumulates SLEB128 bytes into i64 with proper sign extension
  • Fallback: converts accumulated i64 to BigInt and continues with BigInt arithmetic
  • Most real-world Int values fit in i64, avoiding heap allocation entirely

Benchmark (canbench, wasm32)

Metric Before After Change
option_list Decoding 26.2M inst 23.2M inst -11.7%
variant_list Decoding 25.1M inst 22.1M inst -11.9%
option_list Heap 2 pages 1 page -50%
variant_list Heap 2 pages 1 page -50%

No regressions on any of the 9 benchmarks.

Compatibility

Wire format is unchanged. Additional edge-case values added to the round-trip compatibility test (Int(0), Int(i64::MAX), large positive Int).

Relates to #710

@sasa-tomic sasa-tomic requested a review from a team as a code owner March 13, 2026 14:05
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 13, 2026

Name Max Mem (Kb) Encode Decode
blob 4_224 4_207_487 2_122_465
btreemap 73_856 531_975_943 13_058_092_273
nns 192 2_021_253 5_675_179 ($\textcolor{red}{0.04\%}$)
nns_list_proposal 1_216 7_016_131 ($\textcolor{red}{0.02\%}$) 64_370_369 ($\textcolor{red}{0.11\%}$)
option_list 64 715_981 22_086_226 ($\textcolor{red}{1.31\%}$)
text 6_336 4_204_384 7_877_792
variant_list 64 710_969 20_730_750 ($\textcolor{red}{0.67\%}$)
vec_int16 12_480 8_404_689 408_970_132
  • Parser cost: 16_179_361
  • Extra args: 2_838_484 ($\textcolor{red}{0.00\%}$)
Click to see raw report
---------------------------------------------------

Benchmark: blob
  total:
    instructions: 6.33 M (no change)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 4.21 M (no change)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 2.12 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: btreemap
  total:
    instructions: 13.59 B (no change)
    heap_increase: 1154 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 531.98 M (no change)
    heap_increase: 159 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 13.06 B (no change)
    heap_increase: 995 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: extra_args
  total:
    instructions: 2.84 M (0.00%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: nns
  total:
    instructions: 24.71 M (0.01%) (change within noise threshold)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  0. Parsing (scope):
    calls: 1 (no change)
    instructions: 16.18 M (no change)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 2.02 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 5.68 M (0.04%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: nns_list_proposal
  total:
    instructions: 71.39 M (0.10%) (change within noise threshold)
    heap_increase: 19 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 7.02 M (0.02%) (change within noise threshold)
    heap_increase: 5 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 64.37 M (0.11%) (change within noise threshold)
    heap_increase: 14 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: option_list
  total:
    instructions: 22.80 M (1.27%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 715.98 K (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 22.09 M (1.31%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: text
  total:
    instructions: 12.08 M (no change)
    heap_increase: 99 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 4.20 M (no change)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 7.88 M (no change)
    heap_increase: 33 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: variant_list
  total:
    instructions: 21.44 M (0.65%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 710.97 K (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 20.73 M (0.67%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_int16
  total:
    instructions: 417.38 M (no change)
    heap_increase: 195 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 8.40 M (no change)
    heap_increase: 130 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 408.97 M (no change)
    heap_increase: 65 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Summary:
  instructions:
    status:   No significant changes 👍
    counts:   [total 9 | regressed 0 | improved 0 | new 0 | unchanged 9]
    change:   [max +285.95K | p75 +72.95K | median +72 | p25 0 | min 0]
    change %: [max +1.27% | p75 +0.10% | median 0.00% | p25 0.00% | min 0.00%]

  heap_increase:
    status:   No significant changes 👍
    counts:   [total 9 | regressed 0 | improved 0 | new 0 | unchanged 9]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 9 | regressed 0 | improved 0 | new 0 | unchanged 9]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------
Successfully persisted results to canbench_results.yml

@lwshang lwshang changed the base branch from sat-perf-improvements to master March 15, 2026 17:49
sasa-tomic and others added 2 commits March 15, 2026 14:05
Decode SLEB128-encoded Int values into i64 first, only falling back
to BigInt for values that exceed 64-bit range. Mirrors the existing
Nat::decode fast path.

Benchmark: option_list decoding 26.2M → 23.2M instructions (-11.7%),
variant_list decoding 25.1M → 22.1M instructions (-11.9%),
heap usage halved for both.

Wire format is unchanged.

Made-with: Cursor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lwshang lwshang force-pushed the sat-perf-int-decode branch from a17141e to db3bdea Compare March 15, 2026 18:09
@lwshang lwshang merged commit 325b275 into master Mar 15, 2026
11 checks passed
@lwshang lwshang deleted the sat-perf-int-decode branch March 15, 2026 18:11
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.

2 participants