From 21f439cb1aaa7d6b7dc8ad754f436c60ce041dfc Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Wed, 25 Jan 2023 20:59:19 -0300 Subject: [PATCH] reduce exec time of fast-unstake benchmarks (#13120) * reduce exec time of fast-unstake benchmarks * fix test * fmt * fix patch the tests * fix patch the tests * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * add batch size as well * update some benches to be better * fix one last test * fix * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * reduce time even more * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * fix tests * nit * remove * improve the weight calc further * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * fix benchmarks * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * update * fix * fix * fmt * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * lots of changes again... * smaller input * update * fmt * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * cleanup * small simplification * fmt * reduce exec time a bit * fix * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * test * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * increase again * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake * review comments * fmt * fix * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_fast_unstake Co-authored-by: command-bot <> --- bin/node/runtime/src/lib.rs | 5 +- frame/fast-unstake/src/benchmarking.rs | 38 +++--- frame/fast-unstake/src/lib.rs | 126 ++++++++++++------ frame/fast-unstake/src/mock.rs | 3 + frame/fast-unstake/src/tests.rs | 173 ++++++------------------- frame/fast-unstake/src/weights.rs | 155 ++++++++++++---------- 6 files changed, 237 insertions(+), 263 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 0ac6ade9127e8..1f85d118ea534 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -591,10 +591,13 @@ impl pallet_staking::Config for Runtime { impl pallet_fast_unstake::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ControlOrigin = frame_system::EnsureRoot; - type BatchSize = ConstU32<128>; + type BatchSize = ConstU32<64>; type Deposit = ConstU128<{ DOLLARS }>; type Currency = Balances; type Staking = Staking; + type MaxErasToCheckPerBlock = ConstU32<1>; + #[cfg(feature = "runtime-benchmarks")] + type MaxBackersPerValidator = MaxNominatorRewardedPerValidator; type WeightInfo = (); } diff --git a/frame/fast-unstake/src/benchmarking.rs b/frame/fast-unstake/src/benchmarking.rs index b4a5e21dcfc13..de85502f7b411 100644 --- a/frame/fast-unstake/src/benchmarking.rs +++ b/frame/fast-unstake/src/benchmarking.rs @@ -31,13 +31,11 @@ use sp_staking::{EraIndex, StakingInterface}; use sp_std::prelude::*; const USER_SEED: u32 = 0; -const DEFAULT_BACKER_PER_VALIDATOR: u32 = 128; -const MAX_VALIDATORS: u32 = 128; type CurrencyOf = ::Currency; -fn create_unexposed_nominators() -> Vec { - (0..T::BatchSize::get()) +fn create_unexposed_batch(batch_size: u32) -> Vec { + (0..batch_size) .map(|i| { let account = frame_benchmarking::account::("unexposed_nominator", i, USER_SEED); @@ -76,7 +74,7 @@ fn setup_staking(v: u32, until: EraIndex) { .collect::>(); for era in 0..=until { - let others = (0..DEFAULT_BACKER_PER_VALIDATOR) + let others = (0..T::MaxBackersPerValidator::get()) .map(|s| { let who = frame_benchmarking::account::("nominator", era, s); let value = ed; @@ -97,8 +95,10 @@ fn on_idle_full_block() { benchmarks! { // on_idle, we don't check anyone, but fully unbond them. on_idle_unstake { + let b in 1 .. T::BatchSize::get(); + ErasToCheckPerBlock::::put(1); - for who in create_unexposed_nominators::() { + for who in create_unexposed_batch::(b).into_iter() { assert_ok!(FastUnstake::::register_fast_unstake( RawOrigin::Signed(who.clone()).into(), )); @@ -114,7 +114,7 @@ benchmarks! { checked, stashes, .. - }) if checked.len() == 1 && stashes.len() as u32 == T::BatchSize::get() + }) if checked.len() == 1 && stashes.len() as u32 == b )); } : { @@ -123,25 +123,23 @@ benchmarks! { verify { assert!(matches!( fast_unstake_events::().last(), - Some(Event::BatchFinished) + Some(Event::BatchFinished { size: b }) )); } - // on_idle, when we check some number of eras, + // on_idle, when we check some number of eras and the queue is already set. on_idle_check { - // number of eras multiplied by validators in that era. - let x in (T::Staking::bonding_duration() * 1) .. (T::Staking::bonding_duration() * MAX_VALIDATORS); - - let u = T::Staking::bonding_duration(); - let v = x / u; + let v in 1 .. 256; + let b in 1 .. T::BatchSize::get(); + let u = T::MaxErasToCheckPerBlock::get().min(T::Staking::bonding_duration()); ErasToCheckPerBlock::::put(u); T::Staking::set_current_era(u); - // setup staking with v validators and u eras of data (0..=u) + // setup staking with v validators and u eras of data (0..=u+1) setup_staking::(v, u); - let stashes = create_unexposed_nominators::().into_iter().map(|s| { + let stashes = create_unexposed_batch::(b).into_iter().map(|s| { assert_ok!(FastUnstake::::register_fast_unstake( RawOrigin::Signed(s.clone()).into(), )); @@ -150,6 +148,8 @@ benchmarks! { // no one is queued thus far. assert_eq!(Head::::get(), None); + + Head::::put(UnstakeRequest { stashes: stashes.clone().try_into().unwrap(), checked: Default::default() }); } : { on_idle_full_block::(); @@ -167,7 +167,7 @@ benchmarks! { register_fast_unstake { ErasToCheckPerBlock::::put(1); - let who = create_unexposed_nominators::().get(0).cloned().unwrap(); + let who = create_unexposed_batch::(1).get(0).cloned().unwrap(); whitelist_account!(who); assert_eq!(Queue::::count(), 0); @@ -179,7 +179,7 @@ benchmarks! { deregister { ErasToCheckPerBlock::::put(1); - let who = create_unexposed_nominators::().get(0).cloned().unwrap(); + let who = create_unexposed_batch::(1).get(0).cloned().unwrap(); assert_ok!(FastUnstake::::register_fast_unstake( RawOrigin::Signed(who.clone()).into(), )); @@ -194,7 +194,7 @@ benchmarks! { control { let origin = ::ControlOrigin::successful_origin(); } - : _(origin, 128) + : _(origin, T::MaxErasToCheckPerBlock::get()) verify {} impl_benchmark_test_suite!(Pallet, crate::mock::ExtBuilder::default().build(), crate::mock::Runtime) diff --git a/frame/fast-unstake/src/lib.rs b/frame/fast-unstake/src/lib.rs index c0bffc4427a11..82454a4b8ac7d 100644 --- a/frame/fast-unstake/src/lib.rs +++ b/frame/fast-unstake/src/lib.rs @@ -86,12 +86,9 @@ pub mod pallet { traits::{Defensive, ReservableCurrency, StorageVersion}, }; use frame_system::pallet_prelude::*; - use sp_runtime::{ - traits::{Saturating, Zero}, - DispatchResult, - }; + use sp_runtime::{traits::Zero, DispatchResult}; use sp_staking::{EraIndex, StakingInterface}; - use sp_std::{collections::btree_set::BTreeSet, prelude::*, vec::Vec}; + use sp_std::{prelude::*, vec::Vec}; pub use weights::WeightInfo; #[derive(scale_info::TypeInfo, codec::Encode, codec::Decode, codec::MaxEncodedLen)] @@ -138,6 +135,14 @@ pub mod pallet { /// The weight information of this pallet. type WeightInfo: WeightInfo; + + /// Maximum value for `ErasToCheckPerBlock`. This should be as close as possible, but more + /// than the actual value, in order to have accurate benchmarks. + type MaxErasToCheckPerBlock: Get; + + /// Use only for benchmarking. + #[cfg(feature = "runtime-benchmarks")] + type MaxBackersPerValidator: Get; } /// The current "head of the queue" being unstaked. @@ -173,11 +178,11 @@ pub mod pallet { InternalError, /// A batch was partially checked for the given eras, but the process did not finish. BatchChecked { eras: Vec }, - /// A batch was terminated. + /// A batch of a given size was terminated. /// /// This is always follows by a number of `Unstaked` or `Slashed` events, marking the end /// of the batch. A new batch will be created upon next block. - BatchFinished, + BatchFinished { size: u32 }, } #[pallet::error] @@ -208,6 +213,31 @@ pub mod pallet { Self::do_on_idle(remaining_weight) } + + fn integrity_test() { + sp_std::if_std! { + sp_io::TestExternalities::new_empty().execute_with(|| { + // ensure that the value of `ErasToCheckPerBlock` is less than + // `T::MaxErasToCheckPerBlock`. + assert!( + ErasToCheckPerBlock::::get() <= T::MaxErasToCheckPerBlock::get(), + "the value of `ErasToCheckPerBlock` is greater than `T::MaxErasToCheckPerBlock`", + ); + }); + } + } + + #[cfg(feature = "try-runtime")] + fn try_state(_n: T::BlockNumber) -> Result<(), &'static str> { + // ensure that the value of `ErasToCheckPerBlock` is less than + // `T::MaxErasToCheckPerBlock`. + assert!( + ErasToCheckPerBlock::::get() <= T::MaxErasToCheckPerBlock::get(), + "the value of `ErasToCheckPerBlock` is greater than `T::MaxErasToCheckPerBlock`", + ); + + Ok(()) + } } #[pallet::call] @@ -288,9 +318,10 @@ pub mod pallet { /// Dispatch origin must be signed by the [`Config::ControlOrigin`]. #[pallet::call_index(2)] #[pallet::weight(::WeightInfo::control())] - pub fn control(origin: OriginFor, unchecked_eras_to_check: EraIndex) -> DispatchResult { + pub fn control(origin: OriginFor, eras_to_check: EraIndex) -> DispatchResult { let _ = T::ControlOrigin::ensure_origin(origin)?; - ErasToCheckPerBlock::::put(unchecked_eras_to_check); + ensure!(eras_to_check <= T::MaxErasToCheckPerBlock::get(), Error::::CallNotAllowed); + ErasToCheckPerBlock::::put(eras_to_check); Ok(()) } } @@ -324,27 +355,38 @@ pub mod pallet { /// found out to have no eras to check. At the end of a check cycle, even if they are fully /// checked, we don't finish the process. pub(crate) fn do_on_idle(remaining_weight: Weight) -> Weight { - let mut eras_to_check_per_block = ErasToCheckPerBlock::::get(); + // any weight that is unaccounted for + let mut unaccounted_weight = Weight::from_ref_time(0); + + let eras_to_check_per_block = ErasToCheckPerBlock::::get(); if eras_to_check_per_block.is_zero() { - return T::DbWeight::get().reads(1) + return T::DbWeight::get().reads(1).saturating_add(unaccounted_weight) } // NOTE: here we're assuming that the number of validators has only ever increased, // meaning that the number of exposures to check is either this per era, or less. let validator_count = T::Staking::desired_validator_count(); + let (next_batch_size, reads_from_queue) = Head::::get() + .map_or((Queue::::count().min(T::BatchSize::get()), true), |head| { + (head.stashes.len() as u32, false) + }); // determine the number of eras to check. This is based on both `ErasToCheckPerBlock` // and `remaining_weight` passed on to us from the runtime executive. - let max_weight = |v, u| { - ::WeightInfo::on_idle_check(v * u) - .max(::WeightInfo::on_idle_unstake()) + let max_weight = |v, b| { + // NOTE: this potentially under-counts by up to `BatchSize` reads from the queue. + ::WeightInfo::on_idle_check(v, b) + .max(::WeightInfo::on_idle_unstake(b)) + .saturating_add(if reads_from_queue { + T::DbWeight::get().reads(next_batch_size.into()) + } else { + Zero::zero() + }) }; - while max_weight(validator_count, eras_to_check_per_block).any_gt(remaining_weight) { - eras_to_check_per_block.saturating_dec(); - if eras_to_check_per_block.is_zero() { - log!(debug, "early existing because eras_to_check_per_block is zero"); - return T::DbWeight::get().reads(2) - } + + if max_weight(validator_count, next_batch_size).any_gt(remaining_weight) { + log!(debug, "early exit because eras_to_check_per_block is zero"); + return T::DbWeight::get().reads(3).saturating_add(unaccounted_weight) } if T::Staking::election_ongoing() { @@ -352,7 +394,7 @@ pub mod pallet { // there is an ongoing election -- we better not do anything. Imagine someone is not // exposed anywhere in the last era, and the snapshot for the election is already // taken. In this time period, we don't want to accidentally unstake them. - return T::DbWeight::get().reads(2) + return T::DbWeight::get().reads(4).saturating_add(unaccounted_weight) } let UnstakeRequest { stashes, mut checked } = match Head::::take().or_else(|| { @@ -362,6 +404,9 @@ pub mod pallet { .collect::>() .try_into() .expect("take ensures bound is met; qed"); + unaccounted_weight.saturating_accrue( + T::DbWeight::get().reads_writes(stashes.len() as u64, stashes.len() as u64), + ); if stashes.is_empty() { None } else { @@ -377,10 +422,11 @@ pub mod pallet { log!( debug, - "checking {:?} stashes, eras_to_check_per_block = {:?}, remaining_weight = {:?}", + "checking {:?} stashes, eras_to_check_per_block = {:?}, checked {:?}, remaining_weight = {:?}", stashes.len(), eras_to_check_per_block, - remaining_weight + checked, + remaining_weight, ); // the range that we're allowed to check in this round. @@ -431,11 +477,10 @@ pub mod pallet { } }; - let check_stash = |stash, deposit, eras_checked: &mut BTreeSet| { - let is_exposed = unchecked_eras_to_check.iter().any(|e| { - eras_checked.insert(*e); - T::Staking::is_exposed_in_era(&stash, e) - }); + let check_stash = |stash, deposit| { + let is_exposed = unchecked_eras_to_check + .iter() + .any(|e| T::Staking::is_exposed_in_era(&stash, e)); if is_exposed { T::Currency::slash_reserved(&stash, deposit); @@ -448,20 +493,16 @@ pub mod pallet { }; if unchecked_eras_to_check.is_empty() { - // `stash` is not exposed in any era now -- we can let go of them now. + // `stashes` are not exposed in any era now -- we can let go of them now. + let size = stashes.len() as u32; stashes.into_iter().for_each(|(stash, deposit)| unstake_stash(stash, deposit)); - Self::deposit_event(Event::::BatchFinished); - ::WeightInfo::on_idle_unstake() + Self::deposit_event(Event::::BatchFinished { size }); + ::WeightInfo::on_idle_unstake(size).saturating_add(unaccounted_weight) } else { - // eras checked so far. - let mut eras_checked = BTreeSet::::new(); - let pre_length = stashes.len(); let stashes: BoundedVec<(T::AccountId, BalanceOf), T::BatchSize> = stashes .into_iter() - .filter(|(stash, deposit)| { - check_stash(stash.clone(), *deposit, &mut eras_checked) - }) + .filter(|(stash, deposit)| check_stash(stash.clone(), *deposit)) .collect::>() .try_into() .expect("filter can only lessen the length; still in bound; qed"); @@ -469,8 +510,8 @@ pub mod pallet { log!( debug, - "checked {:?} eras, pre stashes: {:?}, post: {:?}", - eras_checked.len(), + "checked {:?}, pre stashes: {:?}, post: {:?}", + unchecked_eras_to_check, pre_length, post_length, ); @@ -478,7 +519,7 @@ pub mod pallet { match checked.try_extend(unchecked_eras_to_check.clone().into_iter()) { Ok(_) => if stashes.is_empty() { - Self::deposit_event(Event::::BatchFinished); + Self::deposit_event(Event::::BatchFinished { size: 0 }); } else { Head::::put(UnstakeRequest { stashes, checked }); Self::deposit_event(Event::::BatchChecked { @@ -491,9 +532,8 @@ pub mod pallet { }, } - ::WeightInfo::on_idle_check( - validator_count * eras_checked.len() as u32, - ) + ::WeightInfo::on_idle_check(validator_count, pre_length as u32) + .saturating_add(unaccounted_weight) } } } diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index 3f974e5e1a9d6..38cf41fdebe8b 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -185,6 +185,9 @@ impl fast_unstake::Config for Runtime { type ControlOrigin = frame_system::EnsureRoot; type BatchSize = BatchSize; type WeightInfo = (); + type MaxErasToCheckPerBlock = ConstU32<16>; + #[cfg(feature = "runtime-benchmarks")] + type MaxBackersPerValidator = ConstU32<128>; } type Block = frame_system::mocking::MockBlock; diff --git a/frame/fast-unstake/src/tests.rs b/frame/fast-unstake/src/tests.rs index 522aa1d0fac28..3e62146ae299f 100644 --- a/frame/fast-unstake/src/tests.rs +++ b/frame/fast-unstake/src/tests.rs @@ -18,7 +18,7 @@ //! Tests for pallet-fast-unstake. use super::*; -use crate::{mock::*, types::*, weights::WeightInfo, Event}; +use crate::{mock::*, types::*, Event}; use frame_support::{assert_noop, assert_ok, bounded_vec, pallet_prelude::*, traits::Currency}; use pallet_staking::{CurrentEra, RewardDestination}; @@ -236,120 +236,6 @@ mod on_idle { }); } - #[test] - fn respects_weight() { - ExtBuilder::default().build_and_execute(|| { - // we want to check all eras in one block... - ErasToCheckPerBlock::::put(BondingDuration::get() + 1); - CurrentEra::::put(BondingDuration::get()); - - // given - assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(2))); - assert_eq!(Queue::::get(1), Some(Deposit::get())); - - assert_eq!(Queue::::count(), 1); - assert_eq!(Head::::get(), None); - - // when: call fast unstake with not enough weight to process the whole thing, just one - // era. - let remaining_weight = ::WeightInfo::on_idle_check( - pallet_staking::ValidatorCount::::get() * 1, - ); - assert_eq!(FastUnstake::on_idle(0, remaining_weight), remaining_weight); - - // then - assert_eq!( - fast_unstake_events_since_last_call(), - vec![Event::BatchChecked { eras: vec![3] }] - ); - assert_eq!( - Head::::get(), - Some(UnstakeRequest { - stashes: bounded_vec![(1, Deposit::get())], - checked: bounded_vec![3] - }) - ); - - // when: another 1 era. - let remaining_weight = ::WeightInfo::on_idle_check( - pallet_staking::ValidatorCount::::get() * 1, - ); - assert_eq!(FastUnstake::on_idle(0, remaining_weight), remaining_weight); - - // then: - assert_eq!( - fast_unstake_events_since_last_call(), - vec![Event::BatchChecked { eras: bounded_vec![2] }] - ); - assert_eq!( - Head::::get(), - Some(UnstakeRequest { - stashes: bounded_vec![(1, Deposit::get())], - checked: bounded_vec![3, 2] - }) - ); - - // when: then 5 eras, we only need 2 more. - let remaining_weight = ::WeightInfo::on_idle_check( - pallet_staking::ValidatorCount::::get() * 5, - ); - assert_eq!( - FastUnstake::on_idle(0, remaining_weight), - // note the amount of weight consumed: 2 eras worth of weight. - ::WeightInfo::on_idle_check( - pallet_staking::ValidatorCount::::get() * 2, - ) - ); - - // then: - assert_eq!( - fast_unstake_events_since_last_call(), - vec![Event::BatchChecked { eras: vec![1, 0] }] - ); - assert_eq!( - Head::::get(), - Some(UnstakeRequest { - stashes: bounded_vec![(1, Deposit::get())], - checked: bounded_vec![3, 2, 1, 0] - }) - ); - - // when: not enough weight to unstake: - let remaining_weight = - ::WeightInfo::on_idle_unstake() - Weight::from_ref_time(1); - assert_eq!(FastUnstake::on_idle(0, remaining_weight), Weight::from_ref_time(0)); - - // then nothing happens: - assert_eq!(fast_unstake_events_since_last_call(), vec![]); - assert_eq!( - Head::::get(), - Some(UnstakeRequest { - stashes: bounded_vec![(1, Deposit::get())], - checked: bounded_vec![3, 2, 1, 0] - }) - ); - - // when: enough weight to get over at least one iteration: then we are unblocked and can - // unstake. - let remaining_weight = ::WeightInfo::on_idle_check( - pallet_staking::ValidatorCount::::get() * 1, - ); - assert_eq!( - FastUnstake::on_idle(0, remaining_weight), - ::WeightInfo::on_idle_unstake() - ); - - // then we finish the unbonding: - assert_eq!( - fast_unstake_events_since_last_call(), - vec![Event::Unstaked { stash: 1, result: Ok(()) }, Event::BatchFinished], - ); - assert_eq!(Head::::get(), None,); - - assert_unstaked(&1); - }); - } - #[test] fn if_head_not_set_one_random_fetched_from_queue() { ExtBuilder::default().build_and_execute(|| { @@ -410,7 +296,7 @@ mod on_idle { vec![ Event::BatchChecked { eras: vec![3, 2, 1, 0] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished, + Event::BatchFinished { size: 1 }, Event::BatchChecked { eras: vec![3, 2, 1, 0] } ] ); @@ -458,10 +344,10 @@ mod on_idle { vec![ Event::BatchChecked { eras: vec![3, 2, 1, 0] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished, + Event::BatchFinished { size: 1 }, Event::BatchChecked { eras: vec![3, 2, 1, 0] }, Event::Unstaked { stash: 3, result: Ok(()) }, - Event::BatchFinished, + Event::BatchFinished { size: 1 }, ] ); @@ -503,7 +389,7 @@ mod on_idle { vec![ Event::BatchChecked { eras: vec![3, 2, 1, 0] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 1 } ] ); assert_unstaked(&1); @@ -545,7 +431,7 @@ mod on_idle { vec![ Event::BatchChecked { eras: vec![3, 2, 1, 0] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 1 } ] ); assert_unstaked(&1); @@ -620,7 +506,7 @@ mod on_idle { Event::BatchChecked { eras: vec![1] }, Event::BatchChecked { eras: vec![0] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 1 } ] ); assert_unstaked(&1); @@ -704,7 +590,7 @@ mod on_idle { Event::BatchChecked { eras: vec![0] }, Event::BatchChecked { eras: vec![4] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 1 } ] ); assert_unstaked(&1); @@ -799,7 +685,7 @@ mod on_idle { Event::BatchChecked { eras: vec![4] }, Event::BatchChecked { eras: vec![1] }, Event::Unstaked { stash: 1, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 1 } ] ); @@ -843,7 +729,7 @@ mod on_idle { Event::BatchChecked { eras: vec![3] }, Event::BatchChecked { eras: vec![2] }, Event::Slashed { stash: exposed, amount: Deposit::get() }, - Event::BatchFinished + Event::BatchFinished { size: 0 } ] ); }); @@ -879,7 +765,7 @@ mod on_idle { vec![ Event::BatchChecked { eras: vec![3, 2] }, Event::Slashed { stash: exposed, amount: Deposit::get() }, - Event::BatchFinished + Event::BatchFinished { size: 0 } ] ); }); @@ -910,7 +796,10 @@ mod on_idle { assert_eq!( fast_unstake_events_since_last_call(), - vec![Event::Slashed { stash: 100, amount: Deposit::get() }, Event::BatchFinished] + vec![ + Event::Slashed { stash: 100, amount: Deposit::get() }, + Event::BatchFinished { size: 0 } + ] ); }); } @@ -946,7 +835,7 @@ mod on_idle { vec![ Event::BatchChecked { eras: vec![3, 2, 1, 0] }, Event::Unstaked { stash: 42, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 1 } ] ); }); @@ -1001,7 +890,7 @@ mod batched { Event::Unstaked { stash: 1, result: Ok(()) }, Event::Unstaked { stash: 5, result: Ok(()) }, Event::Unstaked { stash: 7, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 3 } ] ); }); @@ -1067,7 +956,7 @@ mod batched { Event::Unstaked { stash: 1, result: Ok(()) }, Event::Unstaked { stash: 5, result: Ok(()) }, Event::Unstaked { stash: 7, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 3 } ] ); }); @@ -1132,7 +1021,7 @@ mod batched { Event::BatchChecked { eras: vec![1, 0] }, Event::Unstaked { stash: 1, result: Ok(()) }, Event::Unstaked { stash: 3, result: Ok(()) }, - Event::BatchFinished + Event::BatchFinished { size: 2 } ] ); }); @@ -1191,10 +1080,32 @@ mod batched { Event::Slashed { stash: 666, amount: Deposit::get() }, Event::BatchChecked { eras: vec![3] }, Event::Slashed { stash: 667, amount: Deposit::get() }, - Event::BatchFinished, + Event::BatchFinished { size: 0 }, Event::BatchChecked { eras: vec![3] } ] ); }); } } + +#[test] +fn kusama_estimate() { + use crate::WeightInfo; + let block_time = frame_support::weights::Weight::from_ref_time( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2, + ) + .ref_time() as f32; + let on_idle = crate::weights::SubstrateWeight::::on_idle_check(1000, 64).ref_time() as f32; + dbg!(block_time, on_idle, on_idle / block_time); +} + +#[test] +fn polkadot_estimate() { + use crate::WeightInfo; + let block_time = frame_support::weights::Weight::from_ref_time( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2, + ) + .ref_time() as f32; + let on_idle = crate::weights::SubstrateWeight::::on_idle_check(300, 64).ref_time() as f32; + dbg!(block_time, on_idle, on_idle / block_time); +} diff --git a/frame/fast-unstake/src/weights.rs b/frame/fast-unstake/src/weights.rs index 6001250e8c24d..f7d0cacba0bcf 100644 --- a/frame/fast-unstake/src/weights.rs +++ b/frame/fast-unstake/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,24 +18,25 @@ //! Autogenerated weights for pallet_fast_unstake //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-11-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2023-01-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `runner-b3zmxxc-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate +// target/production/substrate // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_fast_unstake // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/fast-unstake/src/weights.rs +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_fast_unstake +// --chain=dev // --header=./HEADER-APACHE2 +// --output=./frame/fast-unstake/src/weights.rs // --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -47,8 +48,8 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_fast_unstake. pub trait WeightInfo { - fn on_idle_unstake() -> Weight; - fn on_idle_check(x: u32, ) -> Weight; + fn on_idle_unstake(b: u32, ) -> Weight; + fn on_idle_check(v: u32, b: u32, ) -> Weight; fn register_fast_unstake() -> Weight; fn deregister() -> Weight; fn control() -> Weight; @@ -59,8 +60,9 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) - // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) + // Storage: FastUnstake CounterForQueue (r:1 w:0) + // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking SlashingSpans (r:1 w:0) // Storage: Staking Bonded (r:1 w:1) @@ -70,29 +72,36 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Ledger (r:0 w:1) // Storage: Staking Payee (r:0 w:1) - fn on_idle_unstake() -> Weight { - // Minimum execution time: 82_426 nanoseconds. - Weight::from_ref_time(83_422_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + /// The range of component `b` is `[1, 64]`. + fn on_idle_unstake(b: u32, ) -> Weight { + // Minimum execution time: 92_833 nanoseconds. + Weight::from_ref_time(62_136_346) + // Standard Error: 25_541 + .saturating_add(Weight::from_ref_time(42_904_859).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(b.into()))) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) - // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) - // Storage: FastUnstake Queue (r:2 w:1) - // Storage: FastUnstake CounterForQueue (r:1 w:1) + // Storage: FastUnstake CounterForQueue (r:1 w:0) + // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakers (r:1344 w:0) - /// The range of component `x` is `[672, 86016]`. - fn on_idle_check(x: u32, ) -> Weight { - // Minimum execution time: 13_932_777 nanoseconds. - Weight::from_ref_time(13_996_029_000 as u64) - // Standard Error: 16_878 - .saturating_add(Weight::from_ref_time(18_113_540 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(345 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Storage: Staking ErasStakers (r:2 w:0) + /// The range of component `v` is `[1, 256]`. + /// The range of component `b` is `[1, 64]`. + fn on_idle_check(v: u32, b: u32, ) -> Weight { + // Minimum execution time: 1_775_293 nanoseconds. + Weight::from_ref_time(1_787_133_000) + // Standard Error: 17_109_142 + .saturating_add(Weight::from_ref_time(546_766_552).saturating_mul(v.into())) + // Standard Error: 68_455_625 + .saturating_add(Weight::from_ref_time(2_135_980_830).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) @@ -109,10 +118,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn register_fast_unstake() -> Weight { - // Minimum execution time: 120_190 nanoseconds. - Weight::from_ref_time(121_337_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 124_849 nanoseconds. + Weight::from_ref_time(128_176_000) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) @@ -120,16 +129,16 @@ impl WeightInfo for SubstrateWeight { // Storage: FastUnstake Head (r:1 w:0) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn deregister() -> Weight { - // Minimum execution time: 49_897 nanoseconds. - Weight::from_ref_time(50_080_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 48_246 nanoseconds. + Weight::from_ref_time(49_720_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) fn control() -> Weight { - // Minimum execution time: 4_814 nanoseconds. - Weight::from_ref_time(4_997_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_611 nanoseconds. + Weight::from_ref_time(4_844_000) + .saturating_add(T::DbWeight::get().writes(1)) } } @@ -137,8 +146,9 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) - // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) + // Storage: FastUnstake CounterForQueue (r:1 w:0) + // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking SlashingSpans (r:1 w:0) // Storage: Staking Bonded (r:1 w:1) @@ -148,29 +158,36 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Ledger (r:0 w:1) // Storage: Staking Payee (r:0 w:1) - fn on_idle_unstake() -> Weight { - // Minimum execution time: 82_426 nanoseconds. - Weight::from_ref_time(83_422_000 as u64) - .saturating_add(RocksDbWeight::get().reads(11 as u64)) - .saturating_add(RocksDbWeight::get().writes(6 as u64)) + /// The range of component `b` is `[1, 64]`. + fn on_idle_unstake(b: u32, ) -> Weight { + // Minimum execution time: 92_833 nanoseconds. + Weight::from_ref_time(62_136_346) + // Standard Error: 25_541 + .saturating_add(Weight::from_ref_time(42_904_859).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(6)) + .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(b.into()))) + .saturating_add(RocksDbWeight::get().writes(1)) + .saturating_add(RocksDbWeight::get().writes((5_u64).saturating_mul(b.into()))) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) - // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) - // Storage: FastUnstake Queue (r:2 w:1) - // Storage: FastUnstake CounterForQueue (r:1 w:1) + // Storage: FastUnstake CounterForQueue (r:1 w:0) + // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking ErasStakers (r:1344 w:0) - /// The range of component `x` is `[672, 86016]`. - fn on_idle_check(x: u32, ) -> Weight { - // Minimum execution time: 13_932_777 nanoseconds. - Weight::from_ref_time(13_996_029_000 as u64) - // Standard Error: 16_878 - .saturating_add(Weight::from_ref_time(18_113_540 as u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(345 as u64)) - .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + // Storage: Staking ErasStakers (r:2 w:0) + /// The range of component `v` is `[1, 256]`. + /// The range of component `b` is `[1, 64]`. + fn on_idle_check(v: u32, b: u32, ) -> Weight { + // Minimum execution time: 1_775_293 nanoseconds. + Weight::from_ref_time(1_787_133_000) + // Standard Error: 17_109_142 + .saturating_add(Weight::from_ref_time(546_766_552).saturating_mul(v.into())) + // Standard Error: 68_455_625 + .saturating_add(Weight::from_ref_time(2_135_980_830).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(7)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(RocksDbWeight::get().writes(1)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) @@ -187,10 +204,10 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn register_fast_unstake() -> Weight { - // Minimum execution time: 120_190 nanoseconds. - Weight::from_ref_time(121_337_000 as u64) - .saturating_add(RocksDbWeight::get().reads(14 as u64)) - .saturating_add(RocksDbWeight::get().writes(9 as u64)) + // Minimum execution time: 124_849 nanoseconds. + Weight::from_ref_time(128_176_000) + .saturating_add(RocksDbWeight::get().reads(14)) + .saturating_add(RocksDbWeight::get().writes(9)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) @@ -198,15 +215,15 @@ impl WeightInfo for () { // Storage: FastUnstake Head (r:1 w:0) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn deregister() -> Weight { - // Minimum execution time: 49_897 nanoseconds. - Weight::from_ref_time(50_080_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Minimum execution time: 48_246 nanoseconds. + Weight::from_ref_time(49_720_000) + .saturating_add(RocksDbWeight::get().reads(5)) + .saturating_add(RocksDbWeight::get().writes(2)) } // Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) fn control() -> Weight { - // Minimum execution time: 4_814 nanoseconds. - Weight::from_ref_time(4_997_000 as u64) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_611 nanoseconds. + Weight::from_ref_time(4_844_000) + .saturating_add(RocksDbWeight::get().writes(1)) } }