mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 04:41:03 +00:00
Store election snapshot in a more memory-friendly way. (#9275)
* Store election snapshot in a more memory-friendly way. * fix * re-order benchmarks * Update frame/election-provider-multi-phase/src/lib.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_election_provider_multi_phase --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/election-provider-multi-phase/src/weights.rs --template=./.maintain/frame-weight-template.hbs * manually fix the weights * remove todo Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Parity Bot <admin@parity.io>
This commit is contained in:
@@ -199,6 +199,18 @@ frame_benchmarking::benchmarks! {
|
|||||||
assert!(<MultiPhase<T>>::current_phase().is_unsigned());
|
assert!(<MultiPhase<T>>::current_phase().is_unsigned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_initialize_open_unsigned_without_snapshot {
|
||||||
|
// need to assume signed phase was open before
|
||||||
|
<MultiPhase<T>>::on_initialize_open_signed().unwrap();
|
||||||
|
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||||
|
assert!(<MultiPhase<T>>::current_phase().is_signed());
|
||||||
|
}: {
|
||||||
|
<MultiPhase<T>>::on_initialize_open_unsigned(false, true, 1u32.into()).unwrap();
|
||||||
|
} verify {
|
||||||
|
assert!(<MultiPhase<T>>::snapshot().is_some());
|
||||||
|
assert!(<MultiPhase<T>>::current_phase().is_unsigned());
|
||||||
|
}
|
||||||
|
|
||||||
finalize_signed_phase_accept_solution {
|
finalize_signed_phase_accept_solution {
|
||||||
let receiver = account("receiver", 0, SEED);
|
let receiver = account("receiver", 0, SEED);
|
||||||
let initial_balance = T::Currency::minimum_balance() * 10u32.into();
|
let initial_balance = T::Currency::minimum_balance() * 10u32.into();
|
||||||
@@ -232,18 +244,6 @@ frame_benchmarking::benchmarks! {
|
|||||||
assert_eq!(T::Currency::reserved_balance(&receiver), 0u32.into());
|
assert_eq!(T::Currency::reserved_balance(&receiver), 0u32.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
on_initialize_open_unsigned_without_snapshot {
|
|
||||||
// need to assume signed phase was open before
|
|
||||||
<MultiPhase<T>>::on_initialize_open_signed().unwrap();
|
|
||||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
|
||||||
assert!(<MultiPhase<T>>::current_phase().is_signed());
|
|
||||||
}: {
|
|
||||||
<MultiPhase<T>>::on_initialize_open_unsigned(false, true, 1u32.into()).unwrap();
|
|
||||||
} verify {
|
|
||||||
assert!(<MultiPhase<T>>::snapshot().is_some());
|
|
||||||
assert!(<MultiPhase<T>>::current_phase().is_unsigned());
|
|
||||||
}
|
|
||||||
|
|
||||||
// a call to `<Pallet as ElectionProvider>::elect` where we only return the queued solution.
|
// a call to `<Pallet as ElectionProvider>::elect` where we only return the queued solution.
|
||||||
elect_queued {
|
elect_queued {
|
||||||
// number of votes in snapshot.
|
// number of votes in snapshot.
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ impl BenchmarkingConfig for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Current phase of the pallet.
|
/// 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> {
|
pub enum Phase<Bn> {
|
||||||
/// Nothing, the election is not happening.
|
/// Nothing, the election is not happening.
|
||||||
Off,
|
Off,
|
||||||
@@ -402,7 +402,7 @@ pub enum FallbackStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The type of `Computation` that provided this election data.
|
/// 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 {
|
pub enum ElectionCompute {
|
||||||
/// Election was computed on-chain.
|
/// Election was computed on-chain.
|
||||||
OnChain,
|
OnChain,
|
||||||
@@ -476,7 +476,7 @@ pub struct RoundSnapshot<A> {
|
|||||||
/// This is stored automatically on-chain, and it contains the **size of the entire snapshot**.
|
/// 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
|
/// This is also used in dispatchables as weight witness data and should **only contain the size of
|
||||||
/// the presented solution**, not the entire snapshot.
|
/// 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 {
|
pub struct SolutionOrSnapshotSize {
|
||||||
/// The length of voters.
|
/// The length of voters.
|
||||||
#[codec(compact)]
|
#[codec(compact)]
|
||||||
@@ -1308,12 +1308,29 @@ impl<T: Config> Pallet<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only write snapshot if all existed.
|
// Only write snapshot if all existed.
|
||||||
<SnapshotMetadata<T>>::put(SolutionOrSnapshotSize {
|
let metadata = SolutionOrSnapshotSize {
|
||||||
voters: voters.len() as u32,
|
voters: voters.len() as u32,
|
||||||
targets: targets.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);
|
<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.
|
||||||
|
// `encoded_size` encodes it without storing it anywhere, this should not cause any allocation.
|
||||||
|
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!(buffer.len() == size && size == buffer.capacity());
|
||||||
|
|
||||||
|
sp_io::storage::set(&<Snapshot<T>>::hashed_key(), &buffer);
|
||||||
Ok(w1.saturating_add(w2).saturating_add(w3).saturating_add(T::DbWeight::get().writes(3)))
|
Ok(w1.saturating_add(w2).saturating_add(w3).saturating_add(T::DbWeight::get().writes(3)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user