From a4e366da4b82193cde07d80e5d72085b506a27a5 Mon Sep 17 00:00:00 2001 From: bgallois <benjamin@gallois.cc> Date: Mon, 13 Nov 2023 16:01:30 +0100 Subject: [PATCH] add pallet-quota benchmarks --- pallets/quota/src/benchmarking.rs | 73 +++++++++++++++---- runtime/common/src/weights/pallet_quota.rs | 85 ++++++++++------------ 2 files changed, 100 insertions(+), 58 deletions(-) diff --git a/pallets/quota/src/benchmarking.rs b/pallets/quota/src/benchmarking.rs index 587ff9cc5..ab8785b0f 100644 --- a/pallets/quota/src/benchmarking.rs +++ b/pallets/quota/src/benchmarking.rs @@ -19,46 +19,93 @@ use super::*; use frame_benchmarking::{account, benchmarks}; -// FIXME this is a naïve implementation of benchmarks: -// - without properly prepare data -// - without "verify" blocks -// - without thinking about worst case scenario -// - without writing complexity in the term of refund queue length -// It's there as a seed for benchmark implementation and to use WeightInfo where needed. +fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { + frame_system::Pallet::<T>::assert_has_event(generic_event.into()); +} benchmarks! { where_clause { where IdtyId<T>: From<u32>, BalanceOf<T>: From<u64>, + T::AccountId: From<[u8; 32]>, } queue_refund { let account: T::AccountId = account("Alice", 1, 1); + let dummy_refund = Refund { + account: account.clone(), + identity: 0u32.into(), + amount: 20u64.into(), + }; let refund = Refund { account, identity: 1u32.into(), amount: 10u64.into(), }; - }: { Pallet::<T>::queue_refund(refund) } + // Complexity is bound to MAX_QUEUD_REFUNDS where an insertion is O(n-1) + for i in 0..MAX_QUEUED_REFUNDS-1 { + Pallet::<T>::queue_refund(dummy_refund.clone()) + } + }: { Pallet::<T>::queue_refund(refund.clone()) } + verify { + assert_eq!(RefundQueue::<T>::get().last(), Some(refund).as_ref()); + assert_eq!(RefundQueue::<T>::get().len() as u32, MAX_QUEUED_REFUNDS); + } spend_quota { - let idty_id = 1u32; - let amount = 1u64; + let idty_id: IdtyId<T> = 1u32.into(); + let amount = 2u64; + IdtyQuota::<T>::insert( + idty_id, + Quota { + last_use: T::BlockNumber::zero(), + amount: 10u64.into(), + }, + ); }: { Pallet::<T>::spend_quota(idty_id.into(), amount.into()) } + verify { + // Initially 10, updated to 11, minus 2 + assert_eq!(IdtyQuota::<T>::get(idty_id).unwrap().amount, 9u64.into()); + } try_refund { let account: T::AccountId = account("Alice", 1, 1); + let idty_id: IdtyId<T> = 1u32.into(); + IdtyQuota::<T>::insert( + idty_id, + Quota { + last_use: T::BlockNumber::zero(), + amount: 10u64.into(), + }, + ); + let _ = CurrencyOf::<T>:: make_free_balance_be( + &T::RefundAccount::get(),u32::MAX.into(), + ); + // The worst-case scenario is when the refund fails + // and can only be triggered if the account is dead, + // in this case by having no balance in the account. let refund = Refund { - account, + account: account.clone(), identity: 1u32.into(), amount: 10u64.into(), }; }: { Pallet::<T>::try_refund(refund) } + verify { +assert_has_event::<T>(Event::<T>::RefundFailed ( account ).into()); + } do_refund { let account: T::AccountId = account("Alice", 1, 1); + let _ = CurrencyOf::<T>:: make_free_balance_be( + &T::RefundAccount::get(),u32::MAX.into(), + ); + // The worst-case scenario is when the refund fails + // and can only be triggered if the account is dead, + // in this case by having no balance in the account. let refund = Refund { - account, + account: account.clone(), identity: 1u32.into(), amount: 10u64.into(), }; - let amount = 5u64.into(); - }: { Pallet::<T>::do_refund(refund, amount) } + }: { Pallet::<T>::try_refund(refund) } + verify { +assert_has_event::<T>(Event::<T>::RefundFailed ( account ).into()); + } } diff --git a/runtime/common/src/weights/pallet_quota.rs b/runtime/common/src/weights/pallet_quota.rs index eed488194..3c6b91c8e 100644 --- a/runtime/common/src/weights/pallet_quota.rs +++ b/runtime/common/src/weights/pallet_quota.rs @@ -1,41 +1,28 @@ -// Copyright 2021-2022 Axiom-Team -// -// This file is part of Duniter-v2S. -// -// Duniter-v2S is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, version 3 of the License. -// -// Duniter-v2S is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. //! Autogenerated weights for `pallet_quota` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-26, STEPS: `5`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-11-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `Albatros`, CPU: `Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("gdev-benchmark"), DB CACHE: 1024 +//! HOSTNAME: `bgallois-ms7d43`, CPU: `12th Gen Intel(R) Core(TM) i3-12100F` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/debug/duniter +// ./target/release/duniter // benchmark // pallet -// --chain=gdev-benchmark -// --steps=5 -// --repeat=2 -// --pallet=pallet_quota -// --extrinsic=* -// --execution=wasm +// --chain +// dev // --wasm-execution=compiled -// --heap-pages=4096 -// --output=./ -// --header=./file_header.txt +// --pallet +// pallet-quota +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --output=runtime/common/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,10 +39,10 @@ impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> { /// Proof: Quota RefundQueue (max_values: Some(1), max_size: Some(11266), added: 11761, mode: MaxEncodedLen) fn queue_refund() -> Weight { // Proof Size summary in bytes: - // Measured: `42` + // Measured: `11288` // Estimated: `12751` - // Minimum execution time: 73_265_000 picoseconds. - Weight::from_parts(77_698_000, 0) + // Minimum execution time: 7_039_000 picoseconds. + Weight::from_parts(7_295_000, 0) .saturating_add(Weight::from_parts(0, 12751)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -64,32 +51,40 @@ impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> { /// Proof: Quota IdtyQuota (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) fn spend_quota() -> Weight { // Proof Size summary in bytes: - // Measured: `137` + // Measured: `139` // Estimated: `3489` - // Minimum execution time: 147_746_000 picoseconds. - Weight::from_parts(165_850_000, 0) + // Minimum execution time: 3_382_000 picoseconds. + Weight::from_parts(3_655_000, 0) .saturating_add(Weight::from_parts(0, 3489)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: Quota IdtyQuota (r:1 w:1) /// Proof: Quota IdtyQuota (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(126), added: 2601, mode: MaxEncodedLen) fn try_refund() -> Weight { // Proof Size summary in bytes: - // Measured: `137` - // Estimated: `3489` - // Minimum execution time: 367_239_000 picoseconds. - Weight::from_parts(392_186_000, 0) - .saturating_add(Weight::from_parts(0, 3489)) - .saturating_add(T::DbWeight::get().reads(1)) + // Measured: `139` + // Estimated: `3591` + // Minimum execution time: 11_210_000 picoseconds. + Weight::from_parts(11_612_000, 0) + .saturating_add(Weight::from_parts(0, 3591)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: Quota IdtyQuota (r:1 w:1) + /// Proof: Quota IdtyQuota (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(126), added: 2601, mode: MaxEncodedLen) fn do_refund() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 356_707_000 picoseconds. - Weight::from_parts(471_930_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `139` + // Estimated: `3591` + // Minimum execution time: 11_220_000 picoseconds. + Weight::from_parts(11_589_000, 0) + .saturating_add(Weight::from_parts(0, 3591)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } } -- GitLab