From 5b2843c2cdba11dc61d5646fa11ae30c8b3ab695 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Fri, 16 Sep 2022 11:54:17 +0000 Subject: [PATCH] Pre-allocate vectors in SSZ decoding (#3417) ## Issue Addressed Fixes a potential regression in memory fragmentation identified by @paulhauner here: https://github.com/sigp/lighthouse/pull/3371#discussion_r931770045. ## Proposed Changes Immediately allocate a vector with sufficient size to hold all decoded elements in SSZ decoding. The `size_hint` is derived from the range iterator here: https://github.com/sigp/lighthouse/blob/2983235650811437b44199f9c94e517e948a1e9b/consensus/ssz/src/decode/impls.rs#L489 ## Additional Info I'd like to test this out on some infra for a substantial duration to see if it affects total fragmentation. --- consensus/ssz/src/decode/try_from_iter.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/consensus/ssz/src/decode/try_from_iter.rs b/consensus/ssz/src/decode/try_from_iter.rs index 22db02d4fc..1ff89a107f 100644 --- a/consensus/ssz/src/decode/try_from_iter.rs +++ b/consensus/ssz/src/decode/try_from_iter.rs @@ -29,11 +29,18 @@ pub trait TryFromIter: Sized { impl TryFromIter for Vec { type Error = Infallible; - fn try_from_iter(iter: I) -> Result + fn try_from_iter(values: I) -> Result where I: IntoIterator, { - Ok(Self::from_iter(iter)) + // Pre-allocate the expected size of the Vec, which is parsed from the SSZ input bytes as + // `num_items`. This length has already been checked to be less than or equal to the type's + // maximum length in `decode_list_of_variable_length_items`. + let iter = values.into_iter(); + let (_, opt_max_len) = iter.size_hint(); + let mut vec = Vec::with_capacity(opt_max_len.unwrap_or(0)); + vec.extend(iter); + Ok(vec) } }