3

A benchmark test for function with a param like this:

runner_execute {

    let x in 1..10000000;

    ...

    let gas_limit_call = x as u64;

}: {
    ...

    let call_runner_results = T::Runner::call(
        ...
        gas_limit_call,
        ...
    );
}

The benchmark result:

impl WeightInfo for () {
    // Storage: System Account (r:1 w:0)
    // Storage: Ethereum RemainingRingBalance (r:1 w:0)
    // Storage: EVM AccountCodes (r:1 w:0)
    // Storage: EVM AccountStorages (r:1 w:0)
    fn runner_execute(x: u32, ) -> Weight {
        (5_773_816_000 as Weight)
            // Standard Error: 0
            .saturating_add((38_000 as Weight).saturating_mul(x as Weight))
            .saturating_add(RocksDbWeight::get().reads(4 as Weight))
            .saturating_add(RocksDbWeight::get().writes(1 as Weight))
    }
}

In terms of db read and write weight, it's very clear, but how do you understand (5_773_816_000 as Weight)? Could I get a more detailed weight consumption report?

1 Answer 1

2

The magic number there is not very helpful, I agree. We will change that here.

One unit of weight is equivalent to 10^-12 seconds.
Your extrinsic therefore always takes at least 5.774 milliseconds to execute.
The 38_000 means that the weight of your extrinsic increases linear for each gas_limit_call by 38 ns.

Currently the execution time, storage Reads/Writes and PoV size are the only thing that are measured.
The weights will also take the PoV size into account soon.

A more detailed report is printed by the node, you should see something like (older versions try --raw):

Pallet: "pallet_lottery", Extrinsic: "set_calls", Lowest values: [], Highest values: [], Steps: 50, Repeat: 20                                                                                                                                 
Raw Storage Info    
========                                                   
Storage: Lottery CallIndices (r:0 w:1)
                                           
Median Slopes Analysis                     
========                         
-- Extrinsic Time --             
                                           
Model:                                     
Time ~=    18.44                 
    + n    0.463                 
              µs                 
                                           
Reads = 0 + (0 * n)              
Writes = 1 + (0 * n)             
                                                     
Min Squares Analysis             
========                         
-- Extrinsic Time --             
                                                     
Data points distribution:        
    n   mean µs  sigma µs       %
    0     17.85     0.127    0.7%          
    1     19.29     0.122    0.6%
    2     19.55     0.113    0.5%                    
    3     19.83     0.246    1.2%
    4     20.36     0.232    1.1%          
    5     20.91     0.138    0.6%                    
    6     21.04     0.133    0.6%                    
    7      21.7     0.133    0.6%                    
    8      22.1     0.155    0.7%                    
    9     22.76     0.232    1.0%                          
   10     22.92     0.196    0.8%                    
                                                     
Quality and confidence:                                    
param     error                                            
n         0.009                                            

Model:                                                     
Time ~=    18.42                                           
    + n    0.466                                           
              µs                                           

Reads = 0 + (0 * n)                                        
Writes = 1 + (0 * n) 

On newer substrate versions its possible to pass in the --json or --json-file <PATH> flags
to access the raw results in a machine-readable manner.

One final tip: Your 10000000 is also a magic number 😀, you could add a Config value instead.

2
  • Thanks for your answer. I just found another point, the second line ((38_000 as Weight).saturating_mul(x as Weight)), do you know how 38_000 is generated? Can I see this as T::Runner::call(...) varying weight consumption as gas_limit_call changes? Apr 13, 2022 at 11:28
  • Yes. The benchmarking uses linear regression to find any linear dependency between the input parameters and the weight. The 38 ns is multiplied with your x aka gas_limit_call. parameter. The exact result and linear model should be printed to console as shown above. PS: Updated my answer. Apr 13, 2022 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.