From 8857e186f9565532db4a2d94f7f598d45d86e72d Mon Sep 17 00:00:00 2001
From: bgallois <benjamin@gallois.cc>
Date: Thu, 16 Nov 2023 12:13:32 +0100
Subject: [PATCH] benchmark process_refund_queue overhead

---
 pallets/quota/src/benchmarking.rs          | 12 ++++++++
 pallets/quota/src/lib.rs                   | 11 ++++++--
 pallets/quota/src/weights.rs               |  4 +++
 runtime/common/src/weights/pallet_quota.rs | 32 ++++++++++++++++------
 4 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/pallets/quota/src/benchmarking.rs b/pallets/quota/src/benchmarking.rs
index ab8785b0f..a9d6d5668 100644
--- a/pallets/quota/src/benchmarking.rs
+++ b/pallets/quota/src/benchmarking.rs
@@ -108,4 +108,16 @@ assert_has_event::<T>(Event::<T>::RefundFailed ( account ).into());
     verify {
 assert_has_event::<T>(Event::<T>::RefundFailed ( account ).into());
     }
+    process_refund_queue {
+        let account: T::AccountId = account("Alice", 1, 1);
+        let dummy_refund = Refund {
+            account: account.clone(),
+            identity: 0u32.into(),
+            amount: 20u64.into(),
+        };
+        // Worst case scenario: the queue is full, and the available weight is maximal.
+        for i in 0 .. MAX_QUEUED_REFUNDS {
+            Pallet::<T>::queue_refund(dummy_refund.clone())
+        }
+    }: { Pallet::<T>::process_refund_queue(Weight::MAX) }
 }
diff --git a/pallets/quota/src/lib.rs b/pallets/quota/src/lib.rs
index eff611f21..d62371b1c 100644
--- a/pallets/quota/src/lib.rs
+++ b/pallets/quota/src/lib.rs
@@ -308,9 +308,14 @@ pub mod pallet {
     impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
         // process refund queue if space left on block
         fn on_idle(_block: T::BlockNumber, remaining_weight: Weight) -> Weight {
-            Self::process_refund_queue(remaining_weight)
-            // opti: benchmark process_refund_queue overhead and substract this from weight limit
-            // .saturating_sub(T::WeightInfo::process_refund_queue())
+            // The overhead is computed as the worst-case scenario for process_refund_queue (i.e., when the queue is full),
+            // minus the length of the queue times the actual weight of one refund operation.
+            let overhead = <T as pallet::Config>::WeightInfo::process_refund_queue()
+                .saturating_sub(
+                    <T as pallet::Config>::WeightInfo::try_refund()
+                        .saturating_mul(MAX_QUEUED_REFUNDS.into()),
+                );
+            Self::process_refund_queue(remaining_weight - overhead)
         }
     }
 }
diff --git a/pallets/quota/src/weights.rs b/pallets/quota/src/weights.rs
index c6cadaf10..08caec2c8 100644
--- a/pallets/quota/src/weights.rs
+++ b/pallets/quota/src/weights.rs
@@ -7,6 +7,7 @@ pub trait WeightInfo {
     fn spend_quota() -> Weight;
     fn try_refund() -> Weight;
     fn do_refund() -> Weight;
+    fn process_refund_queue() -> Weight;
 }
 
 impl WeightInfo for () {
@@ -22,4 +23,7 @@ impl WeightInfo for () {
     fn do_refund() -> Weight {
         Weight::from_parts(999u64, 0)
     }
+    fn process_refund_queue() -> Weight {
+        Weight::from_parts(999u64, 0)
+    }
 }
diff --git a/runtime/common/src/weights/pallet_quota.rs b/runtime/common/src/weights/pallet_quota.rs
index 3c6b91c8e..5e5d3b28d 100644
--- a/runtime/common/src/weights/pallet_quota.rs
+++ b/runtime/common/src/weights/pallet_quota.rs
@@ -2,7 +2,7 @@
 //! Autogenerated weights for `pallet_quota`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-11-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2023-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
 //! HOSTNAME: `bgallois-ms7d43`, CPU: `12th Gen Intel(R) Core(TM) i3-12100F`
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
@@ -41,8 +41,8 @@ impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `11288`
 		//  Estimated: `12751`
-		// Minimum execution time: 7_039_000 picoseconds.
-		Weight::from_parts(7_295_000, 0)
+		// Minimum execution time: 7_180_000 picoseconds.
+		Weight::from_parts(7_381_000, 0)
 			.saturating_add(Weight::from_parts(0, 12751))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -53,8 +53,8 @@ impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `139`
 		//  Estimated: `3489`
-		// Minimum execution time: 3_382_000 picoseconds.
-		Weight::from_parts(3_655_000, 0)
+		// Minimum execution time: 3_393_000 picoseconds.
+		Weight::from_parts(3_569_000, 0)
 			.saturating_add(Weight::from_parts(0, 3489))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -67,8 +67,8 @@ impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `139`
 		//  Estimated: `3591`
-		// Minimum execution time: 11_210_000 picoseconds.
-		Weight::from_parts(11_612_000, 0)
+		// Minimum execution time: 10_638_000 picoseconds.
+		Weight::from_parts(10_976_000, 0)
 			.saturating_add(Weight::from_parts(0, 3591))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -81,10 +81,24 @@ impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `139`
 		//  Estimated: `3591`
-		// Minimum execution time: 11_220_000 picoseconds.
-		Weight::from_parts(11_589_000, 0)
+		// Minimum execution time: 10_470_000 picoseconds.
+		Weight::from_parts(11_046_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 RefundQueue (r:1 w:1)
+	/// Proof: Quota RefundQueue (max_values: Some(1), max_size: Some(11266), added: 11761, mode: MaxEncodedLen)
+	/// Storage: Quota IdtyQuota (r:1 w:1)
+	/// Proof: Quota IdtyQuota (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen)
+	fn process_refund_queue() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `11428`
+		//  Estimated: `12751`
+		// Minimum execution time: 259_194_000 picoseconds.
+		Weight::from_parts(261_006_000, 0)
+			.saturating_add(Weight::from_parts(0, 12751))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
 }
-- 
GitLab