Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Store election snapshot in a more memory-friendly way. #9275

Merged
13 commits merged into from
Jul 12, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions frame/election-provider-multi-phase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl BenchmarkingConfig for () {
}

/// Current phase of the pallet.
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)]
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug)]
pub enum Phase<Bn> {
/// Nothing, the election is not happening.
Off,
Expand Down Expand Up @@ -393,7 +393,7 @@ pub enum FallbackStrategy {
}

/// The type of `Computation` that provided this election data.
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)]
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug)]
pub enum ElectionCompute {
/// Election was computed on-chain.
OnChain,
Expand Down Expand Up @@ -465,7 +465,7 @@ pub struct RoundSnapshot<A> {
/// This is stored automatically on-chain, and it contains the **size of the entire snapshot**.
/// This is also used in dispatchables as weight witness data and should **only contain the size of
/// the presented solution**, not the entire snapshot.
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, Default)]
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, Default)]
pub struct SolutionOrSnapshotSize {
/// The length of voters.
#[codec(compact)]
Expand Down Expand Up @@ -1287,12 +1287,29 @@ impl<T: Config> Pallet<T> {
}

// Only write snapshot if all existed.
<SnapshotMetadata<T>>::put(SolutionOrSnapshotSize {
let metadata = SolutionOrSnapshotSize {
voters: voters.len() as u32,
targets: targets.len() as u32,
});
};
log!(debug, "creating a snapshot with metadata {:?}", metadata);

<SnapshotMetadata<T>>::put(metadata);
<DesiredTargets<T>>::put(desired_targets);
<Snapshot<T>>::put(RoundSnapshot { voters, targets });

// instead of using storage APIs, we do a manual encoding into a fixed-size buffer.
// encode it without storing it anywhere, this should not cause any allocation.
kianenigma marked this conversation as resolved.
Show resolved Hide resolved
let snapshot = RoundSnapshot { voters, targets };
let size = snapshot.encoded_size();
log!(info, "snapshot pre-calculated size {:?}", size);
let mut buffer = Vec::with_capacity(size);
snapshot.encode_to(&mut buffer);

// do some checks.
debug_assert_eq!(buffer, snapshot.encode());
// buffer should have not re-allocated since.
debug_assert_eq!(buffer.len(), size);
kianenigma marked this conversation as resolved.
Show resolved Hide resolved

sp_io::storage::set(&<Snapshot<T>>::hashed_key(), &buffer);
Ok(w1.saturating_add(w2).saturating_add(w3).saturating_add(T::DbWeight::get().writes(3)))
}

Expand Down