mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 09:21:05 +00:00
Move WeightCounter to sp-weights (#12603)
* Move WeightCounter to sp_weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename to WeightMeter and test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix pallet-scheduler for new usage Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update primitives/weights/src/weight_meter.rs Co-authored-by: David <dvdplm@gmail.com> * More tests for can_accrue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove defensive_accrue and fixup consumed_ratio I dont think there is a good use-case for defensive_accrue without saturation. Only in tests maybe, will remove for now until we have a use-case. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: David <dvdplm@gmail.com> Co-authored-by: Gavin Wood <gavin@parity.io>
This commit is contained in:
committed by
GitHub
parent
e04b0c4929
commit
bd2166de79
@@ -26,6 +26,9 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate self as sp_weights;
|
||||
|
||||
mod weight_meter;
|
||||
mod weight_v2;
|
||||
|
||||
use codec::{CompactAs, Decode, Encode, MaxEncodedLen};
|
||||
@@ -40,6 +43,7 @@ use sp_arithmetic::{
|
||||
use sp_core::Get;
|
||||
use sp_debug_derive::RuntimeDebug;
|
||||
|
||||
pub use weight_meter::*;
|
||||
pub use weight_v2::*;
|
||||
|
||||
pub mod constants {
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Contains the `WeightMeter` primitive to meter weight usage.
|
||||
|
||||
use super::Weight;
|
||||
|
||||
use sp_arithmetic::Perbill;
|
||||
|
||||
/// Meters consumed weight and a hard limit for the maximal consumable weight.
|
||||
///
|
||||
/// Can be used to check if enough weight for an operation is available before committing to it.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use sp_weights::{Weight, WeightMeter};
|
||||
///
|
||||
/// // The weight is limited to (10, 0).
|
||||
/// let mut meter = WeightMeter::from_limit(Weight::from_parts(10, 0));
|
||||
/// // There is enough weight remaining for an operation with (5, 0) weight.
|
||||
/// assert!(meter.check_accrue(Weight::from_parts(5, 0)));
|
||||
/// // There is not enough weight remaining for an operation with (6, 0) weight.
|
||||
/// assert!(!meter.check_accrue(Weight::from_parts(6, 0)));
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WeightMeter {
|
||||
/// The already consumed weight.
|
||||
pub consumed: Weight,
|
||||
|
||||
/// The maximal consumable weight.
|
||||
pub limit: Weight,
|
||||
}
|
||||
|
||||
impl WeightMeter {
|
||||
/// Creates [`Self`] from a limit for the maximal consumable weight.
|
||||
pub fn from_limit(limit: Weight) -> Self {
|
||||
Self { consumed: Weight::zero(), limit }
|
||||
}
|
||||
|
||||
/// Creates [`Self`] with the maximal possible limit for the consumable weight.
|
||||
pub fn max_limit() -> Self {
|
||||
Self::from_limit(Weight::MAX)
|
||||
}
|
||||
|
||||
/// The remaining weight that can still be consumed.
|
||||
pub fn remaining(&self) -> Weight {
|
||||
self.limit.saturating_sub(self.consumed)
|
||||
}
|
||||
|
||||
/// The ratio of consumed weight to the limit.
|
||||
///
|
||||
/// Calculates one ratio per component and returns the largest.
|
||||
pub fn consumed_ratio(&self) -> Perbill {
|
||||
let time = Perbill::from_rational(self.consumed.ref_time(), self.limit.ref_time());
|
||||
let pov = Perbill::from_rational(self.consumed.proof_size(), self.limit.proof_size());
|
||||
time.max(pov)
|
||||
}
|
||||
|
||||
/// Consume the given weight after checking that it can be consumed. Otherwise do nothing.
|
||||
pub fn check_accrue(&mut self, w: Weight) -> bool {
|
||||
self.consumed.checked_add(&w).map_or(false, |test| {
|
||||
if test.any_gt(self.limit) {
|
||||
false
|
||||
} else {
|
||||
self.consumed = test;
|
||||
true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Check if the given weight can be consumed.
|
||||
pub fn can_accrue(&self, w: Weight) -> bool {
|
||||
self.consumed.checked_add(&w).map_or(false, |t| t.all_lte(self.limit))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
fn weight_meter_remaining_works() {
|
||||
let mut meter = WeightMeter::from_limit(Weight::from_parts(10, 20));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(5, 0)));
|
||||
assert_eq!(meter.consumed, Weight::from_parts(5, 0));
|
||||
assert_eq!(meter.remaining(), Weight::from_parts(5, 20));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(2, 10)));
|
||||
assert_eq!(meter.consumed, Weight::from_parts(7, 10));
|
||||
assert_eq!(meter.remaining(), Weight::from_parts(3, 10));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(3, 10)));
|
||||
assert_eq!(meter.consumed, Weight::from_parts(10, 20));
|
||||
assert_eq!(meter.remaining(), Weight::from_parts(0, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weight_meter_can_accrue_works() {
|
||||
let meter = WeightMeter::from_limit(Weight::from_parts(1, 1));
|
||||
|
||||
assert!(meter.can_accrue(Weight::from_parts(0, 0)));
|
||||
assert!(meter.can_accrue(Weight::from_parts(1, 1)));
|
||||
assert!(!meter.can_accrue(Weight::from_parts(0, 2)));
|
||||
assert!(!meter.can_accrue(Weight::from_parts(2, 0)));
|
||||
assert!(!meter.can_accrue(Weight::from_parts(2, 2)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weight_meter_check_accrue_works() {
|
||||
let mut meter = WeightMeter::from_limit(Weight::from_parts(2, 2));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(0, 0)));
|
||||
assert!(meter.check_accrue(Weight::from_parts(1, 1)));
|
||||
assert!(!meter.check_accrue(Weight::from_parts(0, 2)));
|
||||
assert!(!meter.check_accrue(Weight::from_parts(2, 0)));
|
||||
assert!(!meter.check_accrue(Weight::from_parts(2, 2)));
|
||||
assert!(meter.check_accrue(Weight::from_parts(0, 1)));
|
||||
assert!(meter.check_accrue(Weight::from_parts(1, 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weight_meter_check_and_can_accrue_works() {
|
||||
let mut meter = WeightMeter::max_limit();
|
||||
|
||||
assert!(meter.can_accrue(Weight::from_parts(u64::MAX, 0)));
|
||||
assert!(meter.check_accrue(Weight::from_parts(u64::MAX, 0)));
|
||||
|
||||
assert!(meter.can_accrue(Weight::from_parts(0, u64::MAX)));
|
||||
assert!(meter.check_accrue(Weight::from_parts(0, u64::MAX)));
|
||||
|
||||
assert!(!meter.can_accrue(Weight::from_parts(0, 1)));
|
||||
assert!(!meter.check_accrue(Weight::from_parts(0, 1)));
|
||||
|
||||
assert!(!meter.can_accrue(Weight::from_parts(1, 0)));
|
||||
assert!(!meter.check_accrue(Weight::from_parts(1, 0)));
|
||||
|
||||
assert!(meter.can_accrue(Weight::zero()));
|
||||
assert!(meter.check_accrue(Weight::zero()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consumed_ratio_works() {
|
||||
let mut meter = WeightMeter::from_limit(Weight::from_parts(10, 20));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(5, 0)));
|
||||
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(50));
|
||||
assert!(meter.check_accrue(Weight::from_parts(0, 12)));
|
||||
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(60));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(2, 0)));
|
||||
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(70));
|
||||
assert!(meter.check_accrue(Weight::from_parts(0, 4)));
|
||||
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(80));
|
||||
|
||||
assert!(meter.check_accrue(Weight::from_parts(3, 0)));
|
||||
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100));
|
||||
assert!(meter.check_accrue(Weight::from_parts(0, 4)));
|
||||
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user