Skip to content

Commit

Permalink
generates erasure codes in-place using mutable references into shreds…
Browse files Browse the repository at this point in the history
…' payload

When making Merkle shreds from data, parity shards are first generated
externally in a vector of vectors:
https://github.com/anza-xyz/agave/blob/6ff4dee5f/ledger/src/shred/merkle.rs#L1325

and then copied into coding shreds payload:
https://github.com/anza-xyz/agave/blob/6ff4dee5f/ledger/src/shred/merkle.rs#L1346

There are also many intermediate vector allocations in the process.

The commit avoids this and minimizes allocations by first initializing
all data and coding shreds in all erasure batches in a single vector.
Then the erasure codes are generated and populated in-place using
mutable references into the coding shreds' payload.
  • Loading branch information
behzadnouri committed Jan 27, 2025
1 parent f5d6ebc commit 1492e51
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 201 deletions.
10 changes: 5 additions & 5 deletions ledger/src/shred.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ pub(crate) fn make_merkle_shreds_from_entries(
reed_solomon_cache,
stats,
)?;
Ok(shreds.into_iter().flatten().map(Shred::from).collect())
Ok(shreds.into_iter().map(Shred::from).collect())
}

// Accepts shreds in the slot range [root + 1, max_slot].
Expand Down Expand Up @@ -1336,6 +1336,7 @@ mod tests {
super::*,
assert_matches::assert_matches,
bincode::serialized_size,
itertools::Itertools,
rand::Rng,
rand_chacha::{rand_core::SeedableRng, ChaChaRng},
rayon::ThreadPoolBuilder,
Expand All @@ -1356,7 +1357,7 @@ mod tests {
data_size: usize,
chained: bool,
is_last_in_slot: bool,
) -> Result<Vec<Vec<merkle::Shred>>, Error> {
) -> Result<Vec<merkle::Shred>, Error> {
let thread_pool = ThreadPoolBuilder::new().num_threads(2).build().unwrap();
let chained_merkle_root = chained.then(|| Hash::new_from_array(rng.gen()));
let parent_offset = rng.gen_range(1..=u16::try_from(slot).unwrap_or(u16::MAX));
Expand Down Expand Up @@ -1504,8 +1505,8 @@ mod tests {
is_last_in_slot,
)
.unwrap();
assert_eq!(shreds.len(), 1);
let shreds: Vec<_> = shreds.into_iter().flatten().map(Shred::from).collect();
let shreds: Vec<_> = shreds.into_iter().map(Shred::from).collect();
assert_eq!(shreds.iter().map(Shred::fec_set_index).dedup().count(), 1);

assert_matches!(shreds[0].shred_type(), ShredType::Data);
let parent_slot = shreds[0].parent().unwrap();
Expand Down Expand Up @@ -2216,7 +2217,6 @@ mod tests {
)
.unwrap()
.into_iter()
.flatten()
.map(Shred::from)
.map(|shred| fill_retransmitter_signature(&mut rng, shred, chained, is_last_in_slot))
.collect();
Expand Down
Loading

0 comments on commit 1492e51

Please sign in to comment.