Skip to content

fix: primitive vec fast-path skip bug + release 0.10.26#720

Merged
lwshang merged 4 commits intomasterfrom
lwshang/fix_primitive_vec_fast_path_skip
Mar 18, 2026
Merged

fix: primitive vec fast-path skip bug + release 0.10.26#720
lwshang merged 4 commits intomasterfrom
lwshang/fix_primitive_vec_fast_path_skip

Conversation

@lwshang
Copy link
Copy Markdown
Contributor

@lwshang lwshang commented Mar 18, 2026

Summary

  • Fix decoding failure when a trailing/extra argument is a primitive vector (vec int8/16/32/64, vec nat8/16/32/64, vec float32/64, vec bool)
  • The fast-path optimization (perf: fast-path exact primitive vector decode #712) skipped setting expect_type/wire_type per element; deserialize_ignored_any then misidentified the element type and corrupted the byte stream
  • Fix: always set element types before calling seed.deserialize, skipping only the add_cost(3) call in the fast path
  • Release candid 0.10.26

Test plan

  • New regression test primitive_vector_is_extra_args in tests/compatibility_vectors.rs covers the exact failure scenario
  • All existing compatibility_vectors tests continue to pass

🤖 Generated with Claude Code

lwshang and others added 4 commits March 17, 2026 20:33
When decoding a trailing/extra argument that is a primitive vector,
`deserialize_ignored_any` relies on `expect_type`/`wire_type` being set
to the element type. The fast path introduced in #712 skipped setting
these, causing `deserialize_ignored_any` to see the outer `Vec<T>` type
and attempt to decode a nested vector instead of a scalar, corrupting
the byte stream.

Fix: always set `expect_type`/`wire_type` to the element type before
calling `seed.deserialize`, and only skip `add_cost(3)` in the fast
path. The `primitive_impl!` macro checks `primitive_vec_fast_path`
before touching these types, so normal decode performance is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lwshang lwshang marked this pull request as ready for review March 18, 2026 00:49
@lwshang lwshang requested a review from a team as a code owner March 18, 2026 00:49
@github-actions
Copy link
Copy Markdown

Name Max Mem (Kb) Encode Decode
blob 4_224 4_207_487 2_122_431
btreemap 73_856 531_976_003 13_022_440_615
nns 192 2_021_253 5_661_508 ($\textcolor{green}{-0.03\%}$)
nns_list_proposal 1_216 7_010_160 ($\textcolor{green}{-0.13\%}$) 64_258_407 ($\textcolor{green}{-0.01\%}$)
option_list 64 716_065 21_934_672
text 6_336 4_204_384 7_877_758
variant_list 64 711_213 20_747_140 ($\textcolor{green}{-0.01\%}$)
vec_int16 12_480 8_404_689 553_673_483 ($\textcolor{red}{35.38\%}$)
vec_nat 9_664 67_095_666 844_307_045 ($\textcolor{red}{0.25\%}$)
vec_nat32 24_768 16_793_297 549_479_471 ($\textcolor{red}{35.75\%}$)
vec_nat64 49_344 33_570_495 557_868_339 ($\textcolor{red}{36.41\%}$)
  • Parser cost: 16_174_059 ($\textcolor{green}{-0.03\%}$)
  • Extra args: 2_838_386 ($\textcolor{green}{-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.55 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.02 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.69 M (-0.03%) (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.17 M (-0.03%) (change within noise threshold)
    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.66 M (-0.03%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

Benchmark: nns_list_proposal
  total:
    instructions: 71.27 M (-0.02%) (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.01 M (-0.13%) (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.26 M (-0.01%) (change within noise threshold)
    heap_increase: 14 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

Benchmark: option_list
  total:
    instructions: 22.65 M (no change)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 21.93 M (no change)
    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.46 M (-0.01%) (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: 711.21 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.75 M (-0.01%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

Benchmark: vec_int16
  total:
    instructions: 562.08 M (regressed by 34.67%)
    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: 553.67 M (regressed by 35.38%)
    heap_increase: 65 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

Benchmark: vec_nat
  total:
    instructions: 911.40 M (0.23%) (change within noise threshold)
    heap_increase: 151 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

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

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

Benchmark: vec_nat32
  total:
    instructions: 566.28 M (regressed by 34.32%)
    heap_increase: 387 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 549.48 M (regressed by 35.75%)
    heap_increase: 129 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

Benchmark: vec_nat64
  total:
    instructions: 591.44 M (regressed by 33.65%)
    heap_increase: 771 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 557.87 M (regressed by 36.41%)
    heap_increase: 257 pages (no change)
    stable_memory_increase: 0 pages (no change)

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

Summary:
  instructions:
    status:   Regressions detected 🔴
    counts:   [total 12 | regressed 3 | improved 0 | new 0 | unchanged 9]
    change:   [max +148.90M | p75 +37.75M | median 0 | p25 -586 | min -16.14K]
    change %: [max +34.67% | p75 +8.58% | median 0.00% | p25 -0.00% | min -0.03%]

  heap_increase:
    status:   No significant changes 👍
    counts:   [total 12 | regressed 0 | improved 0 | new 0 | unchanged 12]
    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 12 | regressed 0 | improved 0 | new 0 | unchanged 12]
    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%]

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

Only significant changes:
| status | name                   | calls |     ins |  ins Δ% |  HI |  HI Δ% | SMI |  SMI Δ% |
|--------|------------------------|-------|---------|---------|-----|--------|-----|---------|
|   +    | vec_nat64::2. Decoding |     1 | 557.87M | +36.41% | 257 |  0.00% |   0 |   0.00% |
|   +    | vec_nat32::2. Decoding |     1 | 549.48M | +35.75% | 129 |  0.00% |   0 |   0.00% |
|   +    | vec_int16::2. Decoding |     1 | 553.67M | +35.38% |  65 |  0.00% |   0 |   0.00% |
|   +    | vec_int16              |       | 562.08M | +34.67% | 195 |  0.00% |   0 |   0.00% |
|   +    | vec_nat32              |       | 566.28M | +34.32% | 387 |  0.00% |   0 |   0.00% |
|   +    | vec_nat64              |       | 591.44M | +33.65% | 771 |  0.00% |   0 |   0.00% |

ins = instructions, HI = heap_increase, SMI = stable_memory_increase, Δ% = percent change

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

@lwshang lwshang merged commit defcf83 into master Mar 18, 2026
11 checks passed
@lwshang lwshang deleted the lwshang/fix_primitive_vec_fast_path_skip branch March 18, 2026 14:03
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