mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 08:11:02 +00:00
Contracts: Only exec parsed code in benchmarks (#3915)
[Weights compare](https://weights.tasty.limo/compare?unit=weight&ignore_errors=true&threshold=10&method=asymptotic&repo=polkadot-sdk&old=master&new=pg%2Fbench_tweaks&path_pattern=substrate%2Fframe%2F**%2Fsrc%2Fweights.rs%2Cpolkadot%2Fruntime%2F*%2Fsrc%2Fweights%2F**%2F*.rs%2Cpolkadot%2Fbridges%2Fmodules%2F*%2Fsrc%2Fweights.rs%2Ccumulus%2F**%2Fweights%2F*.rs%2Ccumulus%2F**%2Fweights%2Fxcm%2F*.rs%2Ccumulus%2F**%2Fsrc%2Fweights.rs) Note: Raw weights change does not mean much here, as this PR reduce the scope of what is benchmarked, they are therefore decreased by a good margin. One should instead print the Schedule using cargo test --features runtime-benchmarks bench_print_schedule -- --nocapture or following the instructions from the [README](https://github.com/paritytech/polkadot-sdk/tree/pg/bench_tweaks/substrate/frame/contracts#schedule) for looking at the Schedule of a specific runtime --------- Co-authored-by: command-bot <>
This commit is contained in:
@@ -338,26 +338,49 @@ impl<T: Config> CodeInfo<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Executable<T> for WasmBlob<T> {
|
||||
fn from_storage(
|
||||
code_hash: CodeHash<T>,
|
||||
gas_meter: &mut GasMeter<T>,
|
||||
) -> Result<Self, DispatchError> {
|
||||
let code_info = <CodeInfoOf<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
|
||||
gas_meter.charge(CodeLoadToken(code_info.code_len))?;
|
||||
let code = <PristineCode<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
|
||||
Ok(Self { code, code_info, code_hash })
|
||||
use crate::{ExecError, ExecReturnValue};
|
||||
use wasmi::Func;
|
||||
enum InstanceOrExecReturn<'a, E: Ext> {
|
||||
Instance((Func, Store<Runtime<'a, E>>)),
|
||||
ExecReturn(ExecReturnValue),
|
||||
}
|
||||
|
||||
type PreExecResult<'a, E> = Result<InstanceOrExecReturn<'a, E>, ExecError>;
|
||||
|
||||
impl<T: Config> WasmBlob<T> {
|
||||
/// Sync the frame's gas meter with the engine's one.
|
||||
pub fn process_result<E: Ext<T = T>>(
|
||||
mut store: Store<Runtime<E>>,
|
||||
result: Result<(), wasmi::Error>,
|
||||
) -> ExecResult {
|
||||
let engine_consumed_total = store.fuel_consumed().expect("Fuel metering is enabled; qed");
|
||||
let gas_meter = store.data_mut().ext().gas_meter_mut();
|
||||
let _ = gas_meter.sync_from_executor(engine_consumed_total)?;
|
||||
store.into_data().to_execution_result(result)
|
||||
}
|
||||
|
||||
fn execute<E: Ext<T = T>>(
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub fn bench_prepare_call<E: Ext<T = T>>(
|
||||
self,
|
||||
ext: &mut E,
|
||||
function: &ExportedFunction,
|
||||
input_data: Vec<u8>,
|
||||
) -> ExecResult {
|
||||
) -> (Func, Store<Runtime<E>>) {
|
||||
use InstanceOrExecReturn::*;
|
||||
match Self::prepare_execute(self, Runtime::new(ext, input_data), &ExportedFunction::Call)
|
||||
.expect("Benchmark should provide valid module")
|
||||
{
|
||||
Instance((func, store)) => (func, store),
|
||||
ExecReturn(_) => panic!("Expected Instance"),
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_execute<'a, E: Ext<T = T>>(
|
||||
self,
|
||||
runtime: Runtime<'a, E>,
|
||||
function: &'a ExportedFunction,
|
||||
) -> PreExecResult<'a, E> {
|
||||
let code = self.code.as_slice();
|
||||
// Instantiate the Wasm module to the engine.
|
||||
let runtime = Runtime::new(ext, input_data);
|
||||
let schedule = <T>::Schedule::get();
|
||||
let (mut store, memory, instance) = Self::instantiate::<crate::wasm::runtime::Env, _>(
|
||||
code,
|
||||
@@ -390,15 +413,6 @@ impl<T: Config> Executable<T> for WasmBlob<T> {
|
||||
.add_fuel(fuel_limit)
|
||||
.expect("We've set up engine to fuel consuming mode; qed");
|
||||
|
||||
// Sync this frame's gas meter with the engine's one.
|
||||
let process_result = |mut store: Store<Runtime<E>>, result| {
|
||||
let engine_consumed_total =
|
||||
store.fuel_consumed().expect("Fuel metering is enabled; qed");
|
||||
let gas_meter = store.data_mut().ext().gas_meter_mut();
|
||||
let _ = gas_meter.sync_from_executor(engine_consumed_total)?;
|
||||
store.into_data().to_execution_result(result)
|
||||
};
|
||||
|
||||
// Start function should already see the correct refcount in case it will be ever inspected.
|
||||
if let &ExportedFunction::Constructor = function {
|
||||
E::increment_refcount(self.code_hash)?;
|
||||
@@ -417,10 +431,37 @@ impl<T: Config> Executable<T> for WasmBlob<T> {
|
||||
Error::<T>::CodeRejected
|
||||
})?;
|
||||
|
||||
let result = exported_func.call(&mut store, &[], &mut []);
|
||||
process_result(store, result)
|
||||
Ok(InstanceOrExecReturn::Instance((exported_func, store)))
|
||||
},
|
||||
Err(err) => process_result(store, Err(err)),
|
||||
Err(err) => Self::process_result(store, Err(err)).map(InstanceOrExecReturn::ExecReturn),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Executable<T> for WasmBlob<T> {
|
||||
fn from_storage(
|
||||
code_hash: CodeHash<T>,
|
||||
gas_meter: &mut GasMeter<T>,
|
||||
) -> Result<Self, DispatchError> {
|
||||
let code_info = <CodeInfoOf<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
|
||||
gas_meter.charge(CodeLoadToken(code_info.code_len))?;
|
||||
let code = <PristineCode<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
|
||||
Ok(Self { code, code_info, code_hash })
|
||||
}
|
||||
|
||||
fn execute<E: Ext<T = T>>(
|
||||
self,
|
||||
ext: &mut E,
|
||||
function: &ExportedFunction,
|
||||
input_data: Vec<u8>,
|
||||
) -> ExecResult {
|
||||
use InstanceOrExecReturn::*;
|
||||
match Self::prepare_execute(self, Runtime::new(ext, input_data), function)? {
|
||||
Instance((func, mut store)) => {
|
||||
let result = func.call(&mut store, &[], &mut []);
|
||||
Self::process_result(store, result)
|
||||
},
|
||||
ExecReturn(exec_return) => Ok(exec_return),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1780,6 +1821,7 @@ mod tests {
|
||||
const CODE_GAS_LEFT: &str = r#"
|
||||
(module
|
||||
(import "seal1" "gas_left" (func $seal_gas_left (param i32 i32)))
|
||||
(import "seal0" "clear_storage" (func $clear_storage (param i32)))
|
||||
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
@@ -1796,6 +1838,9 @@ mod tests {
|
||||
)
|
||||
|
||||
(func (export "call")
|
||||
;; Burn some PoV, clear_storage consumes some PoV as in order to clear the storage we need to we need to read its size first.
|
||||
(call $clear_storage (i32.const 0))
|
||||
|
||||
;; This stores the weight left to the buffer
|
||||
(call $seal_gas_left (i32.const 0) (i32.const 20))
|
||||
|
||||
@@ -1807,6 +1852,9 @@ mod tests {
|
||||
)
|
||||
)
|
||||
|
||||
;; Burn some PoV, clear_storage consumes some PoV as in order to clear the storage we need to we need to read its size first.
|
||||
(call $clear_storage (i32.const 0))
|
||||
|
||||
;; Return weight left and its encoded value len
|
||||
(call $seal_return (i32.const 0) (i32.const 0) (i32.load (i32.const 20)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user