diff --git a/substrate/frame/scheduler/src/benchmarking.rs b/substrate/frame/scheduler/src/benchmarking.rs index d0a14fc73d64..ff40e8ef8abf 100644 --- a/substrate/frame/scheduler/src/benchmarking.rs +++ b/substrate/frame/scheduler/src/benchmarking.rs @@ -17,25 +17,23 @@ //! Scheduler pallet benchmarking. -use super::*; use alloc::vec; -use frame_benchmarking::v1::{account, benchmarks, BenchmarkError}; +use frame_benchmarking::v2::*; use frame_support::{ ensure, traits::{schedule::Priority, BoundedInline}, weights::WeightMeter, }; -use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; +use frame_system::{EventRecord, RawOrigin}; -use crate::Pallet as Scheduler; -use frame_system::{Call as SystemCall, EventRecord}; +use crate::*; -const SEED: u32 = 0; +type SystemCall = frame_system::Call; +type SystemOrigin = ::RuntimeOrigin; +const SEED: u32 = 0; const BLOCK_NUMBER: u32 = 2; -type SystemOrigin = ::RuntimeOrigin; - fn assert_last_event(generic_event: ::RuntimeEvent) { let events = frame_system::Pallet::::events(); let system_event: ::RuntimeEvent = generic_event.into(); @@ -61,7 +59,7 @@ fn fill_schedule( let call = make_call::(None); let period = Some(((i + 100).into(), 100)); let name = u32_to_name(i); - Scheduler::::do_schedule_named(name, t, period, 0, origin.clone(), call)?; + Pallet::::do_schedule_named(name, t, period, 0, origin.clone(), call)?; } ensure!(Agenda::::get(when).len() == n as usize, "didn't fill schedule"); Ok(()) @@ -134,107 +132,160 @@ fn make_origin(signed: bool) -> ::PalletsOrigin { } } -benchmarks! { +#[benchmarks] +mod benchmarks { + use super::*; + // `service_agendas` when no work is done. - service_agendas_base { - let now = BlockNumberFor::::from(BLOCK_NUMBER); + #[benchmark] + fn service_agendas_base() { + let now = BLOCK_NUMBER.into(); IncompleteSince::::put(now - One::one()); - }: { - Scheduler::::service_agendas(&mut WeightMeter::new(), now, 0); - } verify { + + #[block] + { + Pallet::::service_agendas(&mut WeightMeter::new(), now, 0); + } + assert_eq!(IncompleteSince::::get(), Some(now - One::one())); } // `service_agenda` when no work is done. - service_agenda_base { + #[benchmark] + fn service_agenda_base( + s: Linear<0, { T::MaxScheduledPerBlock::get() }>, + ) -> Result<(), BenchmarkError> { let now = BLOCK_NUMBER.into(); - let s in 0 .. T::MaxScheduledPerBlock::get(); fill_schedule::(now, s)?; let mut executed = 0; - }: { - Scheduler::::service_agenda(&mut WeightMeter::new(), &mut executed, now, now, 0); - } verify { + + #[block] + { + Pallet::::service_agenda(&mut WeightMeter::new(), &mut executed, now, now, 0); + } + assert_eq!(executed, 0); + + Ok(()) } // `service_task` when the task is a non-periodic, non-named, non-fetched call which is not // dispatched (e.g. due to being overweight). - service_task_base { + #[benchmark] + fn service_task_base() { let now = BLOCK_NUMBER.into(); let task = make_task::(false, false, false, None, 0); // prevent any tasks from actually being executed as we only want the surrounding weight. let mut counter = WeightMeter::with_limit(Weight::zero()); - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { - //assert_eq!(result, Ok(())); + let _result; + + #[block] + { + _result = Pallet::::service_task(&mut counter, now, now, 0, true, task); + } + + // assert!(_result.is_ok()); } // `service_task` when the task is a non-periodic, non-named, fetched call (with a known // preimage length) and which is not dispatched (e.g. due to being overweight). - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { // Use measured PoV size for the Preimages since we pass in a length witness. Preimage::PreimageFor: Measured - }] - service_task_fetched { - let s in (BoundedInline::bound() as u32) .. (T::Preimages::MAX_LENGTH as u32); + })] + fn service_task_fetched( + s: Linear<{ BoundedInline::bound() as u32 }, { T::Preimages::MAX_LENGTH as u32 }>, + ) { let now = BLOCK_NUMBER.into(); let task = make_task::(false, false, false, Some(s), 0); // prevent any tasks from actually being executed as we only want the surrounding weight. let mut counter = WeightMeter::with_limit(Weight::zero()); - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { + let _result; + + #[block] + { + _result = Pallet::::service_task(&mut counter, now, now, 0, true, task); + } + + // assert!(result.is_ok()); } // `service_task` when the task is a non-periodic, named, non-fetched call which is not // dispatched (e.g. due to being overweight). - service_task_named { + #[benchmark] + fn service_task_named() { let now = BLOCK_NUMBER.into(); let task = make_task::(false, true, false, None, 0); // prevent any tasks from actually being executed as we only want the surrounding weight. let mut counter = WeightMeter::with_limit(Weight::zero()); - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { + let _result; + + #[block] + { + _result = Pallet::::service_task(&mut counter, now, now, 0, true, task); + } + + // assert!(result.is_ok()); } // `service_task` when the task is a periodic, non-named, non-fetched call which is not // dispatched (e.g. due to being overweight). - service_task_periodic { + #[benchmark] + fn service_task_periodic() { let now = BLOCK_NUMBER.into(); let task = make_task::(true, false, false, None, 0); // prevent any tasks from actually being executed as we only want the surrounding weight. let mut counter = WeightMeter::with_limit(Weight::zero()); - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { + let _result; + + #[block] + { + _result = Pallet::::service_task(&mut counter, now, now, 0, true, task); + } + + // assert!(result.is_ok()); } // `execute_dispatch` when the origin is `Signed`, not counting the dispatchable's weight. - execute_dispatch_signed { + #[benchmark] + fn execute_dispatch_signed() -> Result<(), BenchmarkError> { let mut counter = WeightMeter::new(); let origin = make_origin::(true); - let call = T::Preimages::realize(&make_call::(None)).unwrap().0; - }: { - assert!(Scheduler::::execute_dispatch(&mut counter, origin, call).is_ok()); - } - verify { + let call = T::Preimages::realize(&make_call::(None))?.0; + let result; + + #[block] + { + result = Pallet::::execute_dispatch(&mut counter, origin, call); + } + + assert!(result.is_ok()); + + Ok(()) } // `execute_dispatch` when the origin is not `Signed`, not counting the dispatchable's weight. - execute_dispatch_unsigned { + #[benchmark] + fn execute_dispatch_unsigned() -> Result<(), BenchmarkError> { let mut counter = WeightMeter::new(); let origin = make_origin::(false); - let call = T::Preimages::realize(&make_call::(None)).unwrap().0; - }: { - assert!(Scheduler::::execute_dispatch(&mut counter, origin, call).is_ok()); - } - verify { + let call = T::Preimages::realize(&make_call::(None))?.0; + let result; + + #[block] + { + result = Pallet::::execute_dispatch(&mut counter, origin, call); + } + + assert!(result.is_ok()); + + Ok(()) } - schedule { - let s in 0 .. (T::MaxScheduledPerBlock::get() - 1); + #[benchmark] + fn schedule( + s: Linear<0, { T::MaxScheduledPerBlock::get() - 1 }>, + ) -> Result<(), BenchmarkError> { let when = BLOCK_NUMBER.into(); let periodic = Some((BlockNumberFor::::one(), 100)); let priority = 0; @@ -242,24 +293,27 @@ benchmarks! { let call = Box::new(SystemCall::set_storage { items: vec![] }.into()); fill_schedule::(when, s)?; - }: _(RawOrigin::Root, when, periodic, priority, call) - verify { - ensure!( - Agenda::::get(when).len() == (s + 1) as usize, - "didn't add to schedule" - ); + + #[extrinsic_call] + _(RawOrigin::Root, when, periodic, priority, call); + + ensure!(Agenda::::get(when).len() == s as usize + 1, "didn't add to schedule"); + + Ok(()) } - cancel { - let s in 1 .. T::MaxScheduledPerBlock::get(); + #[benchmark] + fn cancel(s: Linear<1, { T::MaxScheduledPerBlock::get() }>) -> Result<(), BenchmarkError> { let when = BLOCK_NUMBER.into(); fill_schedule::(when, s)?; assert_eq!(Agenda::::get(when).len(), s as usize); let schedule_origin = T::ScheduleOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - }: _>(schedule_origin, when, 0) - verify { + + #[extrinsic_call] + _(schedule_origin as SystemOrigin, when, 0); + ensure!( s == 1 || Lookup::::get(u32_to_name(0)).is_none(), "didn't remove from lookup if more than 1 task scheduled for `when`" @@ -273,10 +327,14 @@ benchmarks! { s > 1 || Agenda::::get(when).len() == 0, "remove from schedule if only 1 task scheduled for `when`" ); + + Ok(()) } - schedule_named { - let s in 0 .. (T::MaxScheduledPerBlock::get() - 1); + #[benchmark] + fn schedule_named( + s: Linear<0, { T::MaxScheduledPerBlock::get() - 1 }>, + ) -> Result<(), BenchmarkError> { let id = u32_to_name(s); let when = BLOCK_NUMBER.into(); let periodic = Some((BlockNumberFor::::one(), 100)); @@ -285,21 +343,26 @@ benchmarks! { let call = Box::new(SystemCall::set_storage { items: vec![] }.into()); fill_schedule::(when, s)?; - }: _(RawOrigin::Root, id, when, periodic, priority, call) - verify { - ensure!( - Agenda::::get(when).len() == (s + 1) as usize, - "didn't add to schedule" - ); + + #[extrinsic_call] + _(RawOrigin::Root, id, when, periodic, priority, call); + + ensure!(Agenda::::get(when).len() == s as usize + 1, "didn't add to schedule"); + + Ok(()) } - cancel_named { - let s in 1 .. T::MaxScheduledPerBlock::get(); + #[benchmark] + fn cancel_named( + s: Linear<1, { T::MaxScheduledPerBlock::get() }>, + ) -> Result<(), BenchmarkError> { let when = BLOCK_NUMBER.into(); fill_schedule::(when, s)?; - }: _(RawOrigin::Root, u32_to_name(0)) - verify { + + #[extrinsic_call] + _(RawOrigin::Root, u32_to_name(0)); + ensure!( s == 1 || Lookup::::get(u32_to_name(0)).is_none(), "didn't remove from lookup if more than 1 task scheduled for `when`" @@ -313,33 +376,49 @@ benchmarks! { s > 1 || Agenda::::get(when).len() == 0, "remove from schedule if only 1 task scheduled for `when`" ); + + Ok(()) } - schedule_retry { - let s in 1 .. T::MaxScheduledPerBlock::get(); + #[benchmark] + fn schedule_retry( + s: Linear<1, { T::MaxScheduledPerBlock::get() }>, + ) -> Result<(), BenchmarkError> { let when = BLOCK_NUMBER.into(); fill_schedule::(when, s)?; let name = u32_to_name(s - 1); let address = Lookup::::get(name).unwrap(); - let period: BlockNumberFor = 1u32.into(); - let root: ::PalletsOrigin = frame_system::RawOrigin::Root.into(); + let period: BlockNumberFor = 1_u32.into(); let retry_config = RetryConfig { total_retries: 10, remaining: 10, period }; Retries::::insert(address, retry_config); let (mut when, index) = address; let task = Agenda::::get(when)[index as usize].clone().unwrap(); let mut weight_counter = WeightMeter::with_limit(T::MaximumWeight::get()); - }: { - Scheduler::::schedule_retry(&mut weight_counter, when, when, index, &task, retry_config); - } verify { + + #[block] + { + Pallet::::schedule_retry( + &mut weight_counter, + when, + when, + index, + &task, + retry_config, + ); + } + when = when + BlockNumberFor::::one(); assert_eq!( Retries::::get((when, 0)), Some(RetryConfig { total_retries: 10, remaining: 9, period }) ); + + Ok(()) } - set_retry { + #[benchmark] + fn set_retry() -> Result<(), BenchmarkError> { let s = T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); @@ -348,8 +427,10 @@ benchmarks! { let address = Lookup::::get(name).unwrap(); let (when, index) = address; let period = BlockNumberFor::::one(); - }: _(RawOrigin::Root, (when, index), 10, period) - verify { + + #[extrinsic_call] + _(RawOrigin::Root, (when, index), 10, period); + assert_eq!( Retries::::get((when, index)), Some(RetryConfig { total_retries: 10, remaining: 10, period }) @@ -357,9 +438,12 @@ benchmarks! { assert_last_event::( Event::RetrySet { task: address, id: None, period, retries: 10 }.into(), ); + + Ok(()) } - set_retry_named { + #[benchmark] + fn set_retry_named() -> Result<(), BenchmarkError> { let s = T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); @@ -368,8 +452,10 @@ benchmarks! { let address = Lookup::::get(name).unwrap(); let (when, index) = address; let period = BlockNumberFor::::one(); - }: _(RawOrigin::Root, name, 10, period) - verify { + + #[extrinsic_call] + _(RawOrigin::Root, name, 10, period); + assert_eq!( Retries::::get((when, index)), Some(RetryConfig { total_retries: 10, remaining: 10, period }) @@ -377,9 +463,12 @@ benchmarks! { assert_last_event::( Event::RetrySet { task: address, id: Some(name), period, retries: 10 }.into(), ); + + Ok(()) } - cancel_retry { + #[benchmark] + fn cancel_retry() -> Result<(), BenchmarkError> { let s = T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); @@ -388,16 +477,19 @@ benchmarks! { let address = Lookup::::get(name).unwrap(); let (when, index) = address; let period = BlockNumberFor::::one(); - assert!(Scheduler::::set_retry(RawOrigin::Root.into(), (when, index), 10, period).is_ok()); - }: _(RawOrigin::Root, (when, index)) - verify { + assert!(Pallet::::set_retry(RawOrigin::Root.into(), (when, index), 10, period).is_ok()); + + #[extrinsic_call] + _(RawOrigin::Root, (when, index)); + assert!(!Retries::::contains_key((when, index))); - assert_last_event::( - Event::RetryCancelled { task: address, id: None }.into(), - ); + assert_last_event::(Event::RetryCancelled { task: address, id: None }.into()); + + Ok(()) } - cancel_retry_named { + #[benchmark] + fn cancel_retry_named() -> Result<(), BenchmarkError> { let s = T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); @@ -406,14 +498,20 @@ benchmarks! { let address = Lookup::::get(name).unwrap(); let (when, index) = address; let period = BlockNumberFor::::one(); - assert!(Scheduler::::set_retry_named(RawOrigin::Root.into(), name, 10, period).is_ok()); - }: _(RawOrigin::Root, name) - verify { + assert!(Pallet::::set_retry_named(RawOrigin::Root.into(), name, 10, period).is_ok()); + + #[extrinsic_call] + _(RawOrigin::Root, name); + assert!(!Retries::::contains_key((when, index))); - assert_last_event::( - Event::RetryCancelled { task: address, id: Some(name) }.into(), - ); + assert_last_event::(Event::RetryCancelled { task: address, id: Some(name) }.into()); + + Ok(()) } - impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite! { + Pallet, + mock::new_test_ext(), + mock::Test + } }