Skip to content

Commit

Permalink
refactor(pallet-gear): Rewrite alloc benchmark with more common way (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mertwole authored Jul 12, 2023
1 parent df995d2 commit 9986c1d
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 58 deletions.
2 changes: 1 addition & 1 deletion core-backend/common/src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ where
.map_err(Into::into)
}

#[host(cost = RuntimeCosts::Alloc)]
#[host(cost = RuntimeCosts::Alloc(pages))]
pub fn alloc(ctx: &mut R, pages: u32) -> Result<u32, R::Error> {
let res = ctx.alloc(pages);
let res = ctx.process_alloc_func_result(res)?;
Expand Down
2 changes: 1 addition & 1 deletion core-backend/sandbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ pub mod memory;
pub mod runtime;

pub use env::SandboxEnvironment;
pub use memory::MemoryWrap;
pub use memory::{DefaultExecutorMemory, MemoryWrap};
5 changes: 4 additions & 1 deletion core-backend/sandbox/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ use gear_core::{
memory::{HostPointer, Memory, MemoryError},
pages::{PageNumber, PageU32Size, WasmPage},
};
use gear_sandbox::{default_executor::Memory as DefaultExecutorMemory, SandboxMemory};
use gear_core_errors::MemoryError;
use gear_sandbox::SandboxMemory;

pub type DefaultExecutorMemory = gear_sandbox::default_executor::Memory;

/// Wrapper for sp_sandbox::Memory.
pub struct MemoryWrap(DefaultExecutorMemory);
Expand Down
13 changes: 10 additions & 3 deletions core/src/costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ pub struct HostFnWeights {
/// Weight of calling `alloc`.
pub alloc: u64,

/// Weight per allocated page for `alloc`.
pub alloc_per_page: u64,

/// Weight of calling `alloc`.
pub free: u64,

Expand Down Expand Up @@ -313,8 +316,8 @@ impl Token for RuntimeToken {
pub enum RuntimeCosts {
/// Charge zero gas
Null,
/// Weight of calling `alloc`.
Alloc,
/// Weight of calling `alloc` per amount of pages.
Alloc(u32),
/// Weight of calling `free`.
Free,
/// Weight of calling `gr_reserve_gas`.
Expand Down Expand Up @@ -446,9 +449,13 @@ impl RuntimeCosts {
};
}

let cost_with_weight_per_page = |call_weight: u64, weight_per_page: u64, pages: u32| {
call_weight.saturating_add(weight_per_page.saturating_mul(pages as u64))
};

let weight = match *self {
Null => 0,
Alloc => s.alloc,
Alloc(pages) => cost_with_weight_per_page(s.alloc, s.alloc_per_page, pages),
Free => s.free,
ReserveGas => s.gr_reserve_gas,
UnreserveGas => s.gr_unreserve_gas,
Expand Down
4 changes: 2 additions & 2 deletions core/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ mod tests {

#[test]
fn charge_token_fails() {
let token = RuntimeCosts::Alloc.token(&HostFnWeights {
let token = RuntimeCosts::Alloc(0).token(&HostFnWeights {
alloc: 1_000,
..Default::default()
});
Expand All @@ -371,7 +371,7 @@ mod tests {

#[test]
fn charge_allowance_token_fails() {
let token = RuntimeCosts::Alloc.token(&HostFnWeights {
let token = RuntimeCosts::Alloc(0).token(&HostFnWeights {
alloc: 1_000,
..Default::default()
});
Expand Down
1 change: 1 addition & 0 deletions gsdk/src/metadata/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,7 @@ pub mod runtime_types {
#[derive(Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode)]
pub struct HostFnWeights {
pub alloc: runtime_types::sp_weights::weight_v2::Weight,
pub alloc_per_page: runtime_types::sp_weights::weight_v2::Weight,
pub free: runtime_types::sp_weights::weight_v2::Weight,
pub gr_reserve_gas: runtime_types::sp_weights::weight_v2::Weight,
pub gr_unreserve_gas: runtime_types::sp_weights::weight_v2::Weight,
Expand Down
37 changes: 31 additions & 6 deletions pallets/gear/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ use self::{
sandbox::Sandbox,
};
use crate::{
manager::ExtManager, pallet, schedule::INSTR_BENCHMARK_BATCH_SIZE, BalanceOf, BenchmarkStorage,
Call, Config, Event, ExecutionEnvironment, Ext as Externalities, GasHandlerOf, MailboxOf,
Pallet as Gear, Pallet, ProgramStorageOf, QueueOf, RentFreePeriodOf, ResumeMinimalPeriodOf,
Schedule,
manager::ExtManager,
pallet,
schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE},
BalanceOf, BenchmarkStorage, Call, Config, Event, ExecutionEnvironment, Ext as Externalities,
GasHandlerOf, MailboxOf, Pallet as Gear, Pallet, ProgramStorageOf, QueueOf, RentFreePeriodOf,
ResumeMinimalPeriodOf, Schedule,
};
use ::alloc::{
collections::{BTreeMap, BTreeSet},
Expand All @@ -82,16 +84,18 @@ use frame_support::{
};
use frame_system::{Pallet as SystemPallet, RawOrigin};
use gear_backend_common::Environment;
use gear_backend_sandbox::{DefaultExecutorMemory, MemoryWrap};
use gear_core::{
code::{Code, CodeAndId},
gas::{GasAllowanceCounter, GasCounter, ValueCounter},
ids::{CodeId, MessageId, ProgramId},
memory::{AllocationsContext, PageBuf},
memory::{AllocationsContext, Memory, PageBuf},
message::{ContextSettings, DispatchKind, IncomingDispatch, MessageContext},
pages::{GearPage, PageU32Size, WasmPage, GEAR_PAGE_SIZE, WASM_PAGE_SIZE},
reservation::GasReserver,
};
use gear_core_errors::*;
use gear_sandbox::SandboxMemory;
use gear_wasm_instrument::{
parity_wasm::elements::{BlockType, BrTableData, Instruction, SignExtInstruction, ValueType},
syscalls::SysCallName,
Expand Down Expand Up @@ -821,10 +825,22 @@ benchmarks! {
Gear::<T>::reinstrument_code(code_id, &schedule);
}

// Alloc there 1 page because `alloc` execution time is non-linear along with other amounts of pages.
alloc {
let r in 0 .. API_BENCHMARK_BATCHES;
let mut res = None;
let exec = Benches::<T>::alloc(r)?;
let exec = Benches::<T>::alloc(r, 1)?;
}: {
res.replace(run_process(exec));
}
verify {
verify_process(res.unwrap());
}

alloc_per_page {
let p in 1 .. MAX_PAGES;
let mut res = None;
let exec = Benches::<T>::alloc(1, p)?;
}: {
res.replace(run_process(exec));
}
Expand Down Expand Up @@ -1656,6 +1672,15 @@ benchmarks! {
verify_process(res.unwrap());
}

mem_grow {
let r in 0 .. API_BENCHMARK_BATCHES;
let mut mem = MemoryWrap::new(DefaultExecutorMemory::new(1, None).unwrap());
}: {
for _ in 0..(r * API_BENCHMARK_BATCH_SIZE) {
mem.grow(1.into()).unwrap();
}
}

// w_load = w_bench
instr_i64load {
// Increased interval in order to increase accuracy
Expand Down
42 changes: 33 additions & 9 deletions pallets/gear/src/benchmarking/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,24 @@ where
)
}

fn prepare_handle_override_max_pages(
module: ModuleDefinition,
value: u32,
max_pages: WasmPage,
) -> Result<Exec<T>, &'static str> {
let instance = Program::<T>::new(module.into(), vec![])?;
utils::prepare_exec::<T>(
instance.caller.into_origin(),
HandleKind::Handle(ProgramId::from_origin(instance.addr)),
vec![],
PrepareConfig {
value: value.into(),
max_pages_override: Some(max_pages),
..Default::default()
},
)
}

fn prepare_handle_with_reservation_slots(
module: ModuleDefinition,
repetitions: u32,
Expand Down Expand Up @@ -158,24 +176,30 @@ where
)
}

pub fn alloc(r: u32) -> Result<Exec<T>, &'static str> {
pub fn alloc(repetitions: u32, pages: u32) -> Result<Exec<T>, &'static str> {
const MAX_PAGES_OVERRIDE: u16 = u16::MAX;

assert!(repetitions * pages * API_BENCHMARK_BATCH_SIZE <= MAX_PAGES_OVERRIDE as u32);

let mut instructions = vec![
// Alloc 0 pages take almost the same amount of resources as another amount.
Instruction::I32Const(0),
Instruction::I32Const(pages as i32),
Instruction::Call(0),
Instruction::I32Const(i32::MAX),
Instruction::I32Const(-1),
];

unreachable_condition(&mut instructions, Instruction::I32Eq); // if alloc returns i32::MAX then it's error
unreachable_condition(&mut instructions, Instruction::I32Eq); // if alloc returns -1 then it's error

let module = ModuleDefinition {
memory: Some(ImportedMemory::new(0)),
imported_functions: vec![SysCallName::Alloc],
handle_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &instructions)),
handle_body: Some(body::repeated(
repetitions * API_BENCHMARK_BATCH_SIZE,
&instructions,
)),
..Default::default()
};

Self::prepare_handle(module, 0)
Self::prepare_handle_override_max_pages(module, 0, MAX_PAGES_OVERRIDE.into())
}

pub fn free(r: u32) -> Result<Exec<T>, &'static str> {
Expand All @@ -184,8 +208,8 @@ where
use Instruction::*;
let mut instructions = vec![];
for _ in 0..API_BENCHMARK_BATCH_SIZE {
instructions.extend([I32Const(r as i32), Call(0), I32Const(i32::MAX)]);
unreachable_condition(&mut instructions, I32Eq); // if alloc returns i32::MAX then it's error
instructions.extend([I32Const(r as i32), Call(0), I32Const(-1)]);
unreachable_condition(&mut instructions, I32Eq); // if alloc returns -1 then it's error

for page in 0..r {
instructions.extend([I32Const(page as i32), Call(1), I32Const(0)]);
Expand Down
6 changes: 5 additions & 1 deletion pallets/gear/src/benchmarking/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use gear_core::{
code::{Code, CodeAndId},
ids::{CodeId, MessageId, ProgramId},
message::{Dispatch, DispatchKind, Message, ReplyDetails, SignalDetails},
pages::WasmPage,
};
use sp_core::H256;
use sp_runtime::traits::UniqueSaturatedInto;
Expand Down Expand Up @@ -94,6 +95,7 @@ pub struct PrepareConfig {
pub value: u128,
pub gas_allowance: u64,
pub gas_limit: u64,
pub max_pages_override: Option<WasmPage>,
}

impl Default for PrepareConfig {
Expand All @@ -102,6 +104,7 @@ impl Default for PrepareConfig {
value: 0,
gas_allowance: u64::MAX,
gas_limit: u64::MAX / 2,
max_pages_override: None,
}
}
}
Expand Down Expand Up @@ -257,7 +260,8 @@ where
.get_actor(actor_id)
.ok_or("Program not found in the storage")?;

let block_config = prepare_block_config::<T>();
let mut block_config = prepare_block_config::<T>();
block_config.max_pages = config.max_pages_override.unwrap_or(block_config.max_pages);

let precharged_dispatch = core_processor::precharge_for_program(
&block_config,
Expand Down
14 changes: 11 additions & 3 deletions pallets/gear/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,10 @@ pub struct HostFnWeights<T: Config> {
/// Weight of calling `alloc`.
pub alloc: Weight,

/// Weight of calling `alloc`.
/// Weight per page in `alloc`.
pub alloc_per_page: Weight,

/// Weight of calling `free`.
pub free: Weight,

/// Weight of calling `gr_reserve_gas`.
Expand Down Expand Up @@ -839,6 +842,7 @@ impl<T: Config> HostFnWeights<T> {
pub fn into_core(self) -> CoreHostFnWeights {
CoreHostFnWeights {
alloc: self.alloc.ref_time(),
alloc_per_page: self.alloc_per_page.ref_time(),
free: self.free.ref_time(),
gr_reserve_gas: self.gr_reserve_gas.ref_time(),
gr_unreserve_gas: self.gr_unreserve_gas.ref_time(),
Expand Down Expand Up @@ -954,7 +958,11 @@ impl<T: Config> Default for HostFnWeights<T> {
gr_reply_push_input: to_weight!(cost_batched!(gr_reply_push_input)),
gr_reply_push_input_per_byte: to_weight!(cost_byte!(gr_reply_push_input_per_kb)),

alloc: to_weight!(cost_batched!(alloc)),
// Alloc benchmark causes grow memory calls so we subtract it here as grow is charged separately.
alloc: to_weight!(cost_batched!(alloc))
.saturating_sub(to_weight!(cost_batched!(alloc_per_page)))
.saturating_sub(to_weight!(cost_batched!(mem_grow))),
alloc_per_page: to_weight!(cost_batched!(alloc_per_page)),
free: to_weight!(cost_batched!(free)),
gr_reserve_gas: to_weight!(cost!(gr_reserve_gas)),
gr_system_reserve_gas: to_weight!(cost_batched!(gr_system_reserve_gas)),
Expand Down Expand Up @@ -1066,7 +1074,7 @@ impl<T: Config> Default for MemoryWeights<T> {
.saturating_add(T::DbWeight::get().writes(1).ref_time())),
// TODO: make benches to calculate static page cost and mem grow cost (issue #2226)
static_page: Weight::from_parts(100, 0),
mem_grow: Weight::from_parts(100, 0),
mem_grow: to_weight!(cost_batched!(mem_grow)),
// TODO: make it non-zero for para-chains (issue #2225)
parachain_read_heuristic: Weight::zero(),
_phantom: PhantomData,
Expand Down
Loading

0 comments on commit 9986c1d

Please sign in to comment.