Skip to content

Conversation

michaelsproul
Copy link
Member

@michaelsproul michaelsproul commented Aug 28, 2025

Summary of changes

  • Add unsafe fast path for decoding lists and vectors of u8
  • Optimise generic decoding by using chunks_exact and an explicit loop instead of try_fold.

Benchmarks

fixed_vector/decode_u8_1m
                        time:   [18.621 µs 18.719 µs 18.810 µs]
                        change: [−99.737% −99.736% −99.735%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 21 outliers among 100 measurements (21.00%)
  1 (1.00%) low mild
  1 (1.00%) high mild
  19 (19.00%) high severe
  
fixed_vector/encode_u8_1m
                        time:   [953.57 µs 953.66 µs 953.76 µs]
                        change: [−1.1665% −1.0952% −1.0345%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 13 outliers among 100 measurements (13.00%)
  4 (4.00%) high mild
  9 (9.00%) high severe
  
fixed_vector/decode_u64_128k
                        time:   [71.954 µs 71.966 µs 71.979 µs]
                        change: [−60.159% −60.130% −60.103%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
  1 (1.00%) high mild
  8 (8.00%) high severe
  
fixed_vector/encode_u64_128k
                        time:   [65.327 µs 65.401 µs 65.546 µs]
                        change: [−2.6290% −2.5123% −2.3809%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 10 outliers among 100 measurements (10.00%)
  6 (6.00%) high mild
  4 (4.00%) high severe

variable_list/decode_u8_1m
                        time:   [18.874 µs 18.881 µs 18.889 µs]
                        change: [−99.746% −99.745% −99.743%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
  5 (5.00%) high mild
  3 (3.00%) high severe
  
variable_list/encode_u8_1m
                        time:   [1.0696 ms 1.0721 ms 1.0738 ms]
                        change: [+2.7269% +3.3049% +3.8624%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 13 outliers among 100 measurements (13.00%)
  3 (3.00%) low severe
  2 (2.00%) low mild
  4 (4.00%) high mild
  4 (4.00%) high severe
  
variable_list/decode_u64_128k
                        time:   [72.784 µs 73.002 µs 73.246 µs]
                        change: [−59.546% −59.464% −59.387%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 19 outliers among 100 measurements (19.00%)
  17 (17.00%) low severe
  2 (2.00%) high mild
  
variable_list/encode_u64_128k
                        time:   [81.197 µs 81.250 µs 81.307 µs]
                        change: [+1.6473% +1.7150% +1.7862%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 14 outliers among 100 measurements (14.00%)
  5 (5.00%) high mild
  9 (9.00%) high severe

Additional Info

Depends on a new release of ethereum_ssz for:

Encoding is not meaningfully faster, but would need to be optimised in ssz itself (we need to optimise the Vec impl).

Copy link

codecov bot commented Aug 28, 2025

Codecov Report

❌ Patch coverage is 60.00000% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.33%. Comparing base (c557336) to head (d87e180).

Files with missing lines Patch % Lines
src/variable_list.rs 58.33% 10 Missing ⚠️
src/fixed_vector.rs 61.90% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #55      +/-   ##
==========================================
- Coverage   58.62%   58.33%   -0.29%     
==========================================
  Files           8        8              
  Lines         290      324      +34     
==========================================
+ Hits          170      189      +19     
- Misses        120      135      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@michaelsproul michaelsproul changed the title Optimise FixedVector Decode Optimise SSZ encoding and decoding Sep 4, 2025
len: 0,
expected: 1,
})
} else if mem::size_of::<T>() == 1 && mem::align_of::<T>() == 1 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using size_of and align_of removes the need to add any bounds on T. Other crates like bytemuck would have required us to constrain T quite a lot, which sort of defeats the point of a generic impl.

Even using TypeId would have required us to add 'static.

The other advantage of this is that it works for types that encode as u8, like the ParticipationFlags in the BeaconState.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couldn't T be a bool as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I guess it could be, but we never use bools in any consensus data structures, do we?

Would be a good test case

// Safety: We've verified T is u8, so Vec<T> is Vec<u8>
// and bytes.to_vec() produces Vec<u8>
let vec_u8 = bytes.to_vec();
let vec_t = unsafe { std::mem::transmute::<Vec<u8>, Vec<T>>(vec_u8) };
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a test for a type that is not u8

@michaelsproul michaelsproul mentioned this pull request Sep 10, 2025
@michaelsproul michaelsproul mentioned this pull request Sep 30, 2025
4 tasks
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