From 338a9d73a555b9260e2450c540672d0aea5a7e5d Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Mon, 23 Sep 2024 22:57:23 +0200 Subject: [PATCH 1/7] heuristics tests are altered to panic with multiple results --- runtime/common/src/weights.rs | 512 ++++++++++++++++++---------------- runtime/vara/src/tests.rs | 16 +- 2 files changed, 282 insertions(+), 246 deletions(-) diff --git a/runtime/common/src/weights.rs b/runtime/common/src/weights.rs index 74e167b6ad8..98433cb643a 100644 --- a/runtime/common/src/weights.rs +++ b/runtime/common/src/weights.rs @@ -8,254 +8,283 @@ const INSTRUCTIONS_SPREAD: u8 = 50; const SYSCALL_SPREAD: u8 = 10; const PAGES_SPREAD: u8 = 10; -#[track_caller] -fn check_spreading(weight: u64, expected: u64, spread: u8) { - let left = expected - expected * spread as u64 / 100; - let right = expected + expected * spread as u64 / 100; - - assert!( - left <= weight && weight <= right, - "Weight is {weight} ps. Expected weight is {expected} ps. {spread}% spread interval: [{left} ps, {right} ps]" - ); +#[derive(Clone, Copy)] +struct WeightExpectation { + weight: u64, + expected: u64, + spread: u8, + name: &'static str, } -#[track_caller] -fn check_instruction_weight(weight: u32, expected: u32) { - check_spreading(weight.into(), expected.into(), INSTRUCTIONS_SPREAD); -} +impl WeightExpectation { + fn new(weight: u64, expected: u64, spread: u8, name: &'static str) -> Self { + Self { + weight, + expected, + spread, + name, + } + } + + fn check(&self) -> Result<(), String> { + let left = self.expected - self.expected * self.spread as u64 / 100; + let right = self.expected + self.expected * self.spread as u64 / 100; + + if left > self.weight || self.weight > right { + return Err(format!("Instruction [{}]. Weight is {} ps. Expected weight is {} ps. {}% spread interval: [{left} ps, {right} ps]", self.name, self.weight, self.expected, self.spread)); + } -#[track_caller] -fn check_syscall_weight(weight: u64, expected: u64) { - check_spreading(weight, expected, SYSCALL_SPREAD); + Ok(()) + } } -#[track_caller] -fn check_pages_weight(weight: u64, expected: u64) { - check_spreading(weight, expected, PAGES_SPREAD); +fn check_expectations(expectations: &[WeightExpectation]) -> Result<(), Vec> { + let errors = expectations + .iter() + .filter_map(|expectation| { + if let Err(err) = expectation.check() { + Some(err) + } else { + None + } + }) + .collect::>(); + + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } } /// Check that the weights of instructions are within the expected range pub fn check_instructions_weights( weights: InstructionWeights, expected: InstructionWeights, -) { - check_instruction_weight(weights.i64const, expected.i64const); - check_instruction_weight(weights.i64load, expected.i64load); - check_instruction_weight(weights.i32load, expected.i32load); - check_instruction_weight(weights.i64store, expected.i64store); - check_instruction_weight(weights.i32store, expected.i32store); - check_instruction_weight(weights.select, expected.select); - check_instruction_weight(weights.r#if, expected.r#if); - check_instruction_weight(weights.br, expected.br); - check_instruction_weight(weights.br_if, expected.br_if); - check_instruction_weight(weights.br_table, expected.br_table); - check_instruction_weight(weights.br_table_per_entry, expected.br_table_per_entry); - check_instruction_weight(weights.call, expected.call); - check_instruction_weight(weights.call_indirect, expected.call_indirect); - check_instruction_weight( - weights.call_indirect_per_param, - expected.call_indirect_per_param, - ); - check_instruction_weight(weights.call_per_local, expected.call_per_local); - check_instruction_weight(weights.local_get, expected.local_get); - check_instruction_weight(weights.local_set, expected.local_set); - check_instruction_weight(weights.local_tee, expected.local_tee); - check_instruction_weight(weights.global_get, expected.global_get); - check_instruction_weight(weights.global_set, expected.global_set); - check_instruction_weight(weights.memory_current, expected.memory_current); - check_instruction_weight(weights.i64clz, expected.i64clz); - check_instruction_weight(weights.i32clz, expected.i32clz); - check_instruction_weight(weights.i64ctz, expected.i64ctz); - check_instruction_weight(weights.i32ctz, expected.i32ctz); - check_instruction_weight(weights.i64popcnt, expected.i64popcnt); - check_instruction_weight(weights.i32popcnt, expected.i32popcnt); - check_instruction_weight(weights.i64eqz, expected.i64eqz); - check_instruction_weight(weights.i32eqz, expected.i32eqz); - check_instruction_weight(weights.i32extend8s, expected.i32extend8s); - check_instruction_weight(weights.i32extend16s, expected.i32extend16s); - check_instruction_weight(weights.i64extend8s, expected.i64extend8s); - check_instruction_weight(weights.i64extend16s, expected.i64extend16s); - check_instruction_weight(weights.i64extend32s, expected.i64extend32s); - check_instruction_weight(weights.i64extendsi32, expected.i64extendsi32); - check_instruction_weight(weights.i64extendui32, expected.i64extendui32); - check_instruction_weight(weights.i32wrapi64, expected.i32wrapi64); - check_instruction_weight(weights.i64eq, expected.i64eq); - check_instruction_weight(weights.i32eq, expected.i32eq); - check_instruction_weight(weights.i64ne, expected.i64ne); - check_instruction_weight(weights.i32ne, expected.i32ne); - check_instruction_weight(weights.i64lts, expected.i64lts); - check_instruction_weight(weights.i32lts, expected.i32lts); - check_instruction_weight(weights.i64ltu, expected.i64ltu); - check_instruction_weight(weights.i32ltu, expected.i32ltu); - check_instruction_weight(weights.i64gts, expected.i64gts); - check_instruction_weight(weights.i32gts, expected.i32gts); - check_instruction_weight(weights.i64gtu, expected.i64gtu); - check_instruction_weight(weights.i32gtu, expected.i32gtu); - check_instruction_weight(weights.i64les, expected.i64les); - check_instruction_weight(weights.i32les, expected.i32les); - check_instruction_weight(weights.i64leu, expected.i64leu); - check_instruction_weight(weights.i32leu, expected.i32leu); - check_instruction_weight(weights.i64ges, expected.i64ges); - check_instruction_weight(weights.i32ges, expected.i32ges); - check_instruction_weight(weights.i64geu, expected.i64geu); - check_instruction_weight(weights.i32geu, expected.i32geu); - check_instruction_weight(weights.i64add, expected.i64add); - check_instruction_weight(weights.i32add, expected.i32add); - check_instruction_weight(weights.i64sub, expected.i64sub); - check_instruction_weight(weights.i32sub, expected.i32sub); - check_instruction_weight(weights.i64mul, expected.i64mul); - check_instruction_weight(weights.i32mul, expected.i32mul); - check_instruction_weight(weights.i64divs, expected.i64divs); - check_instruction_weight(weights.i32divs, expected.i32divs); - check_instruction_weight(weights.i64divu, expected.i64divu); - check_instruction_weight(weights.i32divu, expected.i32divu); - check_instruction_weight(weights.i64rems, expected.i64rems); - check_instruction_weight(weights.i32rems, expected.i32rems); - check_instruction_weight(weights.i64remu, expected.i64remu); - check_instruction_weight(weights.i32remu, expected.i32remu); - check_instruction_weight(weights.i64and, expected.i64and); - check_instruction_weight(weights.i32and, expected.i32and); - check_instruction_weight(weights.i64or, expected.i64or); - check_instruction_weight(weights.i32or, expected.i32or); - check_instruction_weight(weights.i64xor, expected.i64xor); - check_instruction_weight(weights.i32xor, expected.i32xor); - check_instruction_weight(weights.i64shl, expected.i64shl); - check_instruction_weight(weights.i32shl, expected.i32shl); - check_instruction_weight(weights.i64shrs, expected.i64shrs); - check_instruction_weight(weights.i32shrs, expected.i32shrs); - check_instruction_weight(weights.i64shru, expected.i64shru); - check_instruction_weight(weights.i32shru, expected.i32shru); - check_instruction_weight(weights.i64rotl, expected.i64rotl); - check_instruction_weight(weights.i32rotl, expected.i32rotl); - check_instruction_weight(weights.i64rotr, expected.i64rotr); - check_instruction_weight(weights.i32rotr, expected.i32rotr); +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + weights.$inst_name.into(), + expected.$inst_name.into(), + INSTRUCTIONS_SPREAD, + stringify!($inst_name), + ) + }; + } + + let expectations = vec![ + expectation!(i64const), + expectation!(i64load), + expectation!(i32load), + expectation!(i64store), + expectation!(i32store), + expectation!(select), + expectation!(r#if), + expectation!(br), + expectation!(br_if), + expectation!(br_table), + expectation!(br_table_per_entry), + expectation!(call), + expectation!(call_indirect), + expectation!(call_indirect_per_param), + expectation!(call_per_local), + expectation!(local_get), + expectation!(local_set), + expectation!(local_tee), + expectation!(global_get), + expectation!(global_set), + expectation!(memory_current), + expectation!(i64clz), + expectation!(i32clz), + expectation!(i64ctz), + expectation!(i32ctz), + expectation!(i64popcnt), + expectation!(i32popcnt), + expectation!(i64eqz), + expectation!(i32eqz), + expectation!(i32extend8s), + expectation!(i32extend16s), + expectation!(i64extend8s), + expectation!(i64extend16s), + expectation!(i64extend32s), + expectation!(i64extendsi32), + expectation!(i64extendui32), + expectation!(i32wrapi64), + expectation!(i64eq), + expectation!(i32eq), + expectation!(i64ne), + expectation!(i32ne), + expectation!(i64lts), + expectation!(i32lts), + expectation!(i64ltu), + expectation!(i32ltu), + expectation!(i64gts), + expectation!(i32gts), + expectation!(i64gtu), + expectation!(i32gtu), + expectation!(i64les), + expectation!(i32les), + expectation!(i64leu), + expectation!(i32leu), + expectation!(i64ges), + expectation!(i32ges), + expectation!(i64geu), + expectation!(i32geu), + expectation!(i64add), + expectation!(i32add), + expectation!(i64sub), + expectation!(i32sub), + expectation!(i64mul), + expectation!(i32mul), + expectation!(i64divs), + expectation!(i32divs), + expectation!(i64divu), + expectation!(i32divu), + expectation!(i64rems), + expectation!(i32rems), + expectation!(i64remu), + expectation!(i32remu), + expectation!(i64and), + expectation!(i32and), + expectation!(i64or), + expectation!(i32or), + expectation!(i64xor), + expectation!(i32xor), + expectation!(i64shl), + expectation!(i32shl), + expectation!(i64shrs), + expectation!(i32shrs), + expectation!(i64shru), + expectation!(i32shru), + expectation!(i64rotl), + expectation!(i32rotl), + expectation!(i64rotr), + expectation!(i32rotr), + ]; + + check_expectations(&expectations) } /// Check that the weights of syscalls are within the expected range pub fn check_syscall_weights( weights: SyscallWeights, expected: SyscallWeights, -) { - macro_rules! check { +) -> Result<(), Vec> { + macro_rules! expectation { ($inst_name:ident) => { - check_syscall_weight( + WeightExpectation::new( weights.$inst_name.ref_time(), expected.$inst_name.ref_time(), - ); + SYSCALL_SPREAD, + stringify!($inst_name), + ) }; } - check!(alloc); - check!(free); - check!(free_range); - check!(free_range_per_page); - check!(gr_reserve_gas); - check!(gr_unreserve_gas); - check!(gr_system_reserve_gas); - check!(gr_gas_available); - check!(gr_message_id); - check!(gr_program_id); - check!(gr_source); - check!(gr_value); - check!(gr_value_available); - check!(gr_size); - check!(gr_read); - check!(gr_read_per_byte); - check!(gr_env_vars); - check!(gr_block_height); - check!(gr_block_timestamp); - check!(gr_random); - check!(gr_reply_deposit); - check!(gr_send); - check!(gr_send_per_byte); - check!(gr_send_wgas); - check!(gr_send_wgas_per_byte); - check!(gr_send_init); - check!(gr_send_push); - check!(gr_send_push_per_byte); - check!(gr_send_commit); - check!(gr_send_commit_wgas); - check!(gr_reservation_send); - check!(gr_reservation_send_per_byte); - check!(gr_reservation_send_commit); - check!(gr_reply_commit); - check!(gr_reply_commit_wgas); - check!(gr_reservation_reply); - check!(gr_reservation_reply_per_byte); - check!(gr_reservation_reply_commit); - check!(gr_reply_push); - check!(gr_reply); - check!(gr_reply_per_byte); - check!(gr_reply_wgas); - check!(gr_reply_wgas_per_byte); - check!(gr_reply_push_per_byte); - check!(gr_reply_to); - check!(gr_signal_code); - check!(gr_signal_from); - check!(gr_reply_input); - check!(gr_reply_input_wgas); - check!(gr_reply_push_input); - check!(gr_reply_push_input_per_byte); - check!(gr_send_input); - check!(gr_send_input_wgas); - check!(gr_send_push_input); - check!(gr_send_push_input_per_byte); - check!(gr_debug); - check!(gr_debug_per_byte); - check!(gr_reply_code); - check!(gr_exit); - check!(gr_leave); - check!(gr_wait); - check!(gr_wait_for); - check!(gr_wait_up_to); - check!(gr_wake); - check!(gr_create_program); - check!(gr_create_program_payload_per_byte); - check!(gr_create_program_salt_per_byte); - check!(gr_create_program_wgas); - check!(gr_create_program_wgas_payload_per_byte); - check!(gr_create_program_wgas_salt_per_byte); + let expectations = vec![ + expectation!(alloc), + expectation!(free), + expectation!(free_range), + expectation!(free_range_per_page), + expectation!(gr_reserve_gas), + expectation!(gr_unreserve_gas), + expectation!(gr_system_reserve_gas), + expectation!(gr_gas_available), + expectation!(gr_message_id), + expectation!(gr_program_id), + expectation!(gr_source), + expectation!(gr_value), + expectation!(gr_value_available), + expectation!(gr_size), + expectation!(gr_read), + expectation!(gr_read_per_byte), + expectation!(gr_env_vars), + expectation!(gr_block_height), + expectation!(gr_block_timestamp), + expectation!(gr_random), + expectation!(gr_reply_deposit), + expectation!(gr_send), + expectation!(gr_send_per_byte), + expectation!(gr_send_wgas), + expectation!(gr_send_wgas_per_byte), + expectation!(gr_send_init), + expectation!(gr_send_push), + expectation!(gr_send_push_per_byte), + expectation!(gr_send_commit), + expectation!(gr_send_commit_wgas), + expectation!(gr_reservation_send), + expectation!(gr_reservation_send_per_byte), + expectation!(gr_reservation_send_commit), + expectation!(gr_reply_commit), + expectation!(gr_reply_commit_wgas), + expectation!(gr_reservation_reply), + expectation!(gr_reservation_reply_per_byte), + expectation!(gr_reservation_reply_commit), + expectation!(gr_reply_push), + expectation!(gr_reply), + expectation!(gr_reply_per_byte), + expectation!(gr_reply_wgas), + expectation!(gr_reply_wgas_per_byte), + expectation!(gr_reply_push_per_byte), + expectation!(gr_reply_to), + expectation!(gr_signal_code), + expectation!(gr_signal_from), + expectation!(gr_reply_input), + expectation!(gr_reply_input_wgas), + expectation!(gr_reply_push_input), + expectation!(gr_reply_push_input_per_byte), + expectation!(gr_send_input), + expectation!(gr_send_input_wgas), + expectation!(gr_send_push_input), + expectation!(gr_send_push_input_per_byte), + expectation!(gr_debug), + expectation!(gr_debug_per_byte), + expectation!(gr_reply_code), + expectation!(gr_exit), + expectation!(gr_leave), + expectation!(gr_wait), + expectation!(gr_wait_for), + expectation!(gr_wait_up_to), + expectation!(gr_wake), + expectation!(gr_create_program), + expectation!(gr_create_program_payload_per_byte), + expectation!(gr_create_program_salt_per_byte), + expectation!(gr_create_program_wgas), + expectation!(gr_create_program_wgas_payload_per_byte), + expectation!(gr_create_program_wgas_salt_per_byte), + ]; + + check_expectations(&expectations) } /// Check that the lazy-pages costs are within the expected range pub fn check_lazy_pages_costs( lazy_pages_costs: LazyPagesCosts, expected_lazy_pages_costs: LazyPagesCosts, -) { - check_pages_weight( - lazy_pages_costs.signal_read.cost_for_one(), - expected_lazy_pages_costs.signal_read.cost_for_one(), - ); - check_pages_weight( - lazy_pages_costs.signal_write.cost_for_one(), - expected_lazy_pages_costs.signal_write.cost_for_one(), - ); - check_pages_weight( - lazy_pages_costs.signal_write_after_read.cost_for_one(), - expected_lazy_pages_costs - .signal_write_after_read - .cost_for_one(), - ); - check_pages_weight( - lazy_pages_costs.host_func_read.cost_for_one(), - expected_lazy_pages_costs.host_func_read.cost_for_one(), - ); - check_pages_weight( - lazy_pages_costs.host_func_write.cost_for_one(), - expected_lazy_pages_costs.host_func_write.cost_for_one(), - ); - check_pages_weight( - lazy_pages_costs.host_func_write_after_read.cost_for_one(), - expected_lazy_pages_costs - .host_func_write_after_read - .cost_for_one(), - ); - check_pages_weight( - lazy_pages_costs.load_page_storage_data.cost_for_one(), - expected_lazy_pages_costs - .load_page_storage_data - .cost_for_one(), - ); +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + lazy_pages_costs.$inst_name.cost_for_one(), + expected_lazy_pages_costs.$inst_name.cost_for_one(), + PAGES_SPREAD, + stringify!($inst_name), + ) + }; + } + + let expectations = vec![ + expectation!(signal_read), + expectation!(signal_write), + expectation!(signal_write_after_read), + expectation!(host_func_read), + expectation!(host_func_write), + expectation!(host_func_write_after_read), + expectation!(load_page_storage_data), + ]; + + check_expectations(&expectations) } /// Memory pages access costs. @@ -280,29 +309,28 @@ impl From> for PagesCosts { } /// Check that the pages costs are within the expected range -pub fn check_pages_costs(page_costs: PagesCosts, expected_page_costs: PagesCosts) { - check_pages_weight( - page_costs.load_page_data.cost_for_one(), - expected_page_costs.load_page_data.cost_for_one(), - ); - - check_pages_weight( - page_costs.upload_page_data.cost_for_one(), - expected_page_costs.upload_page_data.cost_for_one(), - ); - - check_pages_weight( - page_costs.mem_grow.cost_for_one(), - expected_page_costs.mem_grow.cost_for_one(), - ); +pub fn check_pages_costs( + page_costs: PagesCosts, + expected_page_costs: PagesCosts, +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + page_costs.$inst_name.cost_for_one(), + expected_page_costs.$inst_name.cost_for_one(), + PAGES_SPREAD, + stringify!($inst_name), + ) + }; + } - check_pages_weight( - page_costs.mem_grow_per_page.cost_for_one(), - expected_page_costs.mem_grow_per_page.cost_for_one(), - ); + let expectations = vec![ + expectation!(load_page_data), + expectation!(upload_page_data), + expectation!(mem_grow), + expectation!(mem_grow_per_page), + expectation!(parachain_read_heuristic), + ]; - check_pages_weight( - page_costs.parachain_read_heuristic.cost_for_one(), - expected_page_costs.parachain_read_heuristic.cost_for_one(), - ); + check_expectations(&expectations) } diff --git a/runtime/vara/src/tests.rs b/runtime/vara/src/tests.rs index 41289598654..fa5e2d14fff 100644 --- a/runtime/vara/src/tests.rs +++ b/runtime/vara/src/tests.rs @@ -224,7 +224,9 @@ fn instruction_weights_heuristics_test() { i32rotr: 300, }; - check_instructions_weights(weights, expected_weights); + let result = check_instructions_weights(weights, expected_weights); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); } #[test] @@ -305,7 +307,9 @@ fn syscall_weights_test() { _phantom: Default::default(), }; - check_syscall_weights(weights, expected); + let result = check_syscall_weights(weights, expected); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); } #[test] @@ -320,7 +324,9 @@ fn page_costs_heuristic_test() { parachain_read_heuristic: 0.into(), }; - check_pages_costs(page_costs, expected_page_costs); + let result = check_pages_costs(page_costs, expected_page_costs); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); } #[test] @@ -337,7 +343,9 @@ fn lazy_page_costs_heuristic_test() { load_page_storage_data: 9_000_000.into(), }; - check_lazy_pages_costs(lazy_pages_costs, expected_lazy_pages_costs); + let result = check_lazy_pages_costs(lazy_pages_costs, expected_lazy_pages_costs); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); } /// Check that it is not possible to write/change memory pages too cheaply, From ec9f02d55d331368ed02bb6fbe1f1f0291cba8eb Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Tue, 24 Sep 2024 11:56:16 +0200 Subject: [PATCH 2/7] weights content have been moved to the tests --- runtime/common/src/lib.rs | 1 - runtime/common/src/weights.rs | 336 --------------------------------- runtime/vara/src/tests.rs | 340 +++++++++++++++++++++++++++++++++- 3 files changed, 335 insertions(+), 342 deletions(-) delete mode 100644 runtime/common/src/weights.rs diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index ac8259048d4..4acb3464385 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -20,7 +20,6 @@ mod apis; pub mod constants; -pub mod weights; use sp_runtime::traits::Get; diff --git a/runtime/common/src/weights.rs b/runtime/common/src/weights.rs deleted file mode 100644 index 98433cb643a..00000000000 --- a/runtime/common/src/weights.rs +++ /dev/null @@ -1,336 +0,0 @@ -use gear_core::{ - costs::{CostOf, LazyPagesCosts}, - pages::GearPagesAmount, -}; -use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; - -const INSTRUCTIONS_SPREAD: u8 = 50; -const SYSCALL_SPREAD: u8 = 10; -const PAGES_SPREAD: u8 = 10; - -#[derive(Clone, Copy)] -struct WeightExpectation { - weight: u64, - expected: u64, - spread: u8, - name: &'static str, -} - -impl WeightExpectation { - fn new(weight: u64, expected: u64, spread: u8, name: &'static str) -> Self { - Self { - weight, - expected, - spread, - name, - } - } - - fn check(&self) -> Result<(), String> { - let left = self.expected - self.expected * self.spread as u64 / 100; - let right = self.expected + self.expected * self.spread as u64 / 100; - - if left > self.weight || self.weight > right { - return Err(format!("Instruction [{}]. Weight is {} ps. Expected weight is {} ps. {}% spread interval: [{left} ps, {right} ps]", self.name, self.weight, self.expected, self.spread)); - } - - Ok(()) - } -} - -fn check_expectations(expectations: &[WeightExpectation]) -> Result<(), Vec> { - let errors = expectations - .iter() - .filter_map(|expectation| { - if let Err(err) = expectation.check() { - Some(err) - } else { - None - } - }) - .collect::>(); - - if errors.is_empty() { - Ok(()) - } else { - Err(errors) - } -} - -/// Check that the weights of instructions are within the expected range -pub fn check_instructions_weights( - weights: InstructionWeights, - expected: InstructionWeights, -) -> Result<(), Vec> { - macro_rules! expectation { - ($inst_name:ident) => { - WeightExpectation::new( - weights.$inst_name.into(), - expected.$inst_name.into(), - INSTRUCTIONS_SPREAD, - stringify!($inst_name), - ) - }; - } - - let expectations = vec![ - expectation!(i64const), - expectation!(i64load), - expectation!(i32load), - expectation!(i64store), - expectation!(i32store), - expectation!(select), - expectation!(r#if), - expectation!(br), - expectation!(br_if), - expectation!(br_table), - expectation!(br_table_per_entry), - expectation!(call), - expectation!(call_indirect), - expectation!(call_indirect_per_param), - expectation!(call_per_local), - expectation!(local_get), - expectation!(local_set), - expectation!(local_tee), - expectation!(global_get), - expectation!(global_set), - expectation!(memory_current), - expectation!(i64clz), - expectation!(i32clz), - expectation!(i64ctz), - expectation!(i32ctz), - expectation!(i64popcnt), - expectation!(i32popcnt), - expectation!(i64eqz), - expectation!(i32eqz), - expectation!(i32extend8s), - expectation!(i32extend16s), - expectation!(i64extend8s), - expectation!(i64extend16s), - expectation!(i64extend32s), - expectation!(i64extendsi32), - expectation!(i64extendui32), - expectation!(i32wrapi64), - expectation!(i64eq), - expectation!(i32eq), - expectation!(i64ne), - expectation!(i32ne), - expectation!(i64lts), - expectation!(i32lts), - expectation!(i64ltu), - expectation!(i32ltu), - expectation!(i64gts), - expectation!(i32gts), - expectation!(i64gtu), - expectation!(i32gtu), - expectation!(i64les), - expectation!(i32les), - expectation!(i64leu), - expectation!(i32leu), - expectation!(i64ges), - expectation!(i32ges), - expectation!(i64geu), - expectation!(i32geu), - expectation!(i64add), - expectation!(i32add), - expectation!(i64sub), - expectation!(i32sub), - expectation!(i64mul), - expectation!(i32mul), - expectation!(i64divs), - expectation!(i32divs), - expectation!(i64divu), - expectation!(i32divu), - expectation!(i64rems), - expectation!(i32rems), - expectation!(i64remu), - expectation!(i32remu), - expectation!(i64and), - expectation!(i32and), - expectation!(i64or), - expectation!(i32or), - expectation!(i64xor), - expectation!(i32xor), - expectation!(i64shl), - expectation!(i32shl), - expectation!(i64shrs), - expectation!(i32shrs), - expectation!(i64shru), - expectation!(i32shru), - expectation!(i64rotl), - expectation!(i32rotl), - expectation!(i64rotr), - expectation!(i32rotr), - ]; - - check_expectations(&expectations) -} - -/// Check that the weights of syscalls are within the expected range -pub fn check_syscall_weights( - weights: SyscallWeights, - expected: SyscallWeights, -) -> Result<(), Vec> { - macro_rules! expectation { - ($inst_name:ident) => { - WeightExpectation::new( - weights.$inst_name.ref_time(), - expected.$inst_name.ref_time(), - SYSCALL_SPREAD, - stringify!($inst_name), - ) - }; - } - - let expectations = vec![ - expectation!(alloc), - expectation!(free), - expectation!(free_range), - expectation!(free_range_per_page), - expectation!(gr_reserve_gas), - expectation!(gr_unreserve_gas), - expectation!(gr_system_reserve_gas), - expectation!(gr_gas_available), - expectation!(gr_message_id), - expectation!(gr_program_id), - expectation!(gr_source), - expectation!(gr_value), - expectation!(gr_value_available), - expectation!(gr_size), - expectation!(gr_read), - expectation!(gr_read_per_byte), - expectation!(gr_env_vars), - expectation!(gr_block_height), - expectation!(gr_block_timestamp), - expectation!(gr_random), - expectation!(gr_reply_deposit), - expectation!(gr_send), - expectation!(gr_send_per_byte), - expectation!(gr_send_wgas), - expectation!(gr_send_wgas_per_byte), - expectation!(gr_send_init), - expectation!(gr_send_push), - expectation!(gr_send_push_per_byte), - expectation!(gr_send_commit), - expectation!(gr_send_commit_wgas), - expectation!(gr_reservation_send), - expectation!(gr_reservation_send_per_byte), - expectation!(gr_reservation_send_commit), - expectation!(gr_reply_commit), - expectation!(gr_reply_commit_wgas), - expectation!(gr_reservation_reply), - expectation!(gr_reservation_reply_per_byte), - expectation!(gr_reservation_reply_commit), - expectation!(gr_reply_push), - expectation!(gr_reply), - expectation!(gr_reply_per_byte), - expectation!(gr_reply_wgas), - expectation!(gr_reply_wgas_per_byte), - expectation!(gr_reply_push_per_byte), - expectation!(gr_reply_to), - expectation!(gr_signal_code), - expectation!(gr_signal_from), - expectation!(gr_reply_input), - expectation!(gr_reply_input_wgas), - expectation!(gr_reply_push_input), - expectation!(gr_reply_push_input_per_byte), - expectation!(gr_send_input), - expectation!(gr_send_input_wgas), - expectation!(gr_send_push_input), - expectation!(gr_send_push_input_per_byte), - expectation!(gr_debug), - expectation!(gr_debug_per_byte), - expectation!(gr_reply_code), - expectation!(gr_exit), - expectation!(gr_leave), - expectation!(gr_wait), - expectation!(gr_wait_for), - expectation!(gr_wait_up_to), - expectation!(gr_wake), - expectation!(gr_create_program), - expectation!(gr_create_program_payload_per_byte), - expectation!(gr_create_program_salt_per_byte), - expectation!(gr_create_program_wgas), - expectation!(gr_create_program_wgas_payload_per_byte), - expectation!(gr_create_program_wgas_salt_per_byte), - ]; - - check_expectations(&expectations) -} - -/// Check that the lazy-pages costs are within the expected range -pub fn check_lazy_pages_costs( - lazy_pages_costs: LazyPagesCosts, - expected_lazy_pages_costs: LazyPagesCosts, -) -> Result<(), Vec> { - macro_rules! expectation { - ($inst_name:ident) => { - WeightExpectation::new( - lazy_pages_costs.$inst_name.cost_for_one(), - expected_lazy_pages_costs.$inst_name.cost_for_one(), - PAGES_SPREAD, - stringify!($inst_name), - ) - }; - } - - let expectations = vec![ - expectation!(signal_read), - expectation!(signal_write), - expectation!(signal_write_after_read), - expectation!(host_func_read), - expectation!(host_func_write), - expectation!(host_func_write_after_read), - expectation!(load_page_storage_data), - ]; - - check_expectations(&expectations) -} - -/// Memory pages access costs. -pub struct PagesCosts { - pub load_page_data: CostOf, - pub upload_page_data: CostOf, - pub mem_grow: CostOf, - pub mem_grow_per_page: CostOf, - pub parachain_read_heuristic: CostOf, -} - -impl From> for PagesCosts { - fn from(val: MemoryWeights) -> Self { - Self { - load_page_data: val.load_page_data.ref_time().into(), - upload_page_data: val.upload_page_data.ref_time().into(), - mem_grow: val.mem_grow.ref_time().into(), - mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), - parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), - } - } -} - -/// Check that the pages costs are within the expected range -pub fn check_pages_costs( - page_costs: PagesCosts, - expected_page_costs: PagesCosts, -) -> Result<(), Vec> { - macro_rules! expectation { - ($inst_name:ident) => { - WeightExpectation::new( - page_costs.$inst_name.cost_for_one(), - expected_page_costs.$inst_name.cost_for_one(), - PAGES_SPREAD, - stringify!($inst_name), - ) - }; - } - - let expectations = vec![ - expectation!(load_page_data), - expectation!(upload_page_data), - expectation!(mem_grow), - expectation!(mem_grow_per_page), - expectation!(parachain_read_heuristic), - ]; - - check_expectations(&expectations) -} diff --git a/runtime/vara/src/tests.rs b/runtime/vara/src/tests.rs index fa5e2d14fff..a9f88b0b5c6 100644 --- a/runtime/vara/src/tests.rs +++ b/runtime/vara/src/tests.rs @@ -20,15 +20,345 @@ use super::*; use crate::Runtime; use frame_support::{dispatch::GetDispatchInfo, traits::StorageInstance}; use frame_system::limits::WeightsPerClass; -use gear_core::costs::LazyPagesCosts; +use gear_core::{ + costs::{CostOf, LazyPagesCosts}, + pages::GearPagesAmount, +}; use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; use pallet_staking::WeightInfo as _; -use runtime_common::weights::{ - check_instructions_weights, check_lazy_pages_costs, check_pages_costs, check_syscall_weights, - PagesCosts, -}; use sp_runtime::AccountId32; +const INSTRUCTIONS_SPREAD: u8 = 50; +const SYSCALL_SPREAD: u8 = 10; +const PAGES_SPREAD: u8 = 10; + +#[derive(Clone, Copy)] +struct WeightExpectation { + weight: u64, + expected: u64, + spread: u8, + name: &'static str, +} + +impl WeightExpectation { + fn new(weight: u64, expected: u64, spread: u8, name: &'static str) -> Self { + Self { + weight, + expected, + spread, + name, + } + } + + fn check(&self) -> Result<(), String> { + let left = self.expected - self.expected * self.spread as u64 / 100; + let right = self.expected + self.expected * self.spread as u64 / 100; + + if left > self.weight || self.weight > right { + return Err(format!("Instruction [{}]. Weight is {} ps. Expected weight is {} ps. {}% spread interval: [{left} ps, {right} ps]", self.name, self.weight, self.expected, self.spread)); + } + + Ok(()) + } +} + +fn check_expectations(expectations: &[WeightExpectation]) -> Result<(), Vec> { + let errors = expectations + .iter() + .filter_map(|expectation| { + if let Err(err) = expectation.check() { + Some(err) + } else { + None + } + }) + .collect::>(); + + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } +} + +/// Check that the weights of instructions are within the expected range +pub fn check_instructions_weights( + weights: InstructionWeights, + expected: InstructionWeights, +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + weights.$inst_name.into(), + expected.$inst_name.into(), + INSTRUCTIONS_SPREAD, + stringify!($inst_name), + ) + }; + } + + let expectations = vec![ + expectation!(i64const), + expectation!(i64load), + expectation!(i32load), + expectation!(i64store), + expectation!(i32store), + expectation!(select), + expectation!(r#if), + expectation!(br), + expectation!(br_if), + expectation!(br_table), + expectation!(br_table_per_entry), + expectation!(call), + expectation!(call_indirect), + expectation!(call_indirect_per_param), + expectation!(call_per_local), + expectation!(local_get), + expectation!(local_set), + expectation!(local_tee), + expectation!(global_get), + expectation!(global_set), + expectation!(memory_current), + expectation!(i64clz), + expectation!(i32clz), + expectation!(i64ctz), + expectation!(i32ctz), + expectation!(i64popcnt), + expectation!(i32popcnt), + expectation!(i64eqz), + expectation!(i32eqz), + expectation!(i32extend8s), + expectation!(i32extend16s), + expectation!(i64extend8s), + expectation!(i64extend16s), + expectation!(i64extend32s), + expectation!(i64extendsi32), + expectation!(i64extendui32), + expectation!(i32wrapi64), + expectation!(i64eq), + expectation!(i32eq), + expectation!(i64ne), + expectation!(i32ne), + expectation!(i64lts), + expectation!(i32lts), + expectation!(i64ltu), + expectation!(i32ltu), + expectation!(i64gts), + expectation!(i32gts), + expectation!(i64gtu), + expectation!(i32gtu), + expectation!(i64les), + expectation!(i32les), + expectation!(i64leu), + expectation!(i32leu), + expectation!(i64ges), + expectation!(i32ges), + expectation!(i64geu), + expectation!(i32geu), + expectation!(i64add), + expectation!(i32add), + expectation!(i64sub), + expectation!(i32sub), + expectation!(i64mul), + expectation!(i32mul), + expectation!(i64divs), + expectation!(i32divs), + expectation!(i64divu), + expectation!(i32divu), + expectation!(i64rems), + expectation!(i32rems), + expectation!(i64remu), + expectation!(i32remu), + expectation!(i64and), + expectation!(i32and), + expectation!(i64or), + expectation!(i32or), + expectation!(i64xor), + expectation!(i32xor), + expectation!(i64shl), + expectation!(i32shl), + expectation!(i64shrs), + expectation!(i32shrs), + expectation!(i64shru), + expectation!(i32shru), + expectation!(i64rotl), + expectation!(i32rotl), + expectation!(i64rotr), + expectation!(i32rotr), + ]; + + check_expectations(&expectations) +} + +/// Check that the weights of syscalls are within the expected range +pub fn check_syscall_weights( + weights: SyscallWeights, + expected: SyscallWeights, +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + weights.$inst_name.ref_time(), + expected.$inst_name.ref_time(), + SYSCALL_SPREAD, + stringify!($inst_name), + ) + }; + } + + let expectations = vec![ + expectation!(alloc), + expectation!(free), + expectation!(free_range), + expectation!(free_range_per_page), + expectation!(gr_reserve_gas), + expectation!(gr_unreserve_gas), + expectation!(gr_system_reserve_gas), + expectation!(gr_gas_available), + expectation!(gr_message_id), + expectation!(gr_program_id), + expectation!(gr_source), + expectation!(gr_value), + expectation!(gr_value_available), + expectation!(gr_size), + expectation!(gr_read), + expectation!(gr_read_per_byte), + expectation!(gr_env_vars), + expectation!(gr_block_height), + expectation!(gr_block_timestamp), + expectation!(gr_random), + expectation!(gr_reply_deposit), + expectation!(gr_send), + expectation!(gr_send_per_byte), + expectation!(gr_send_wgas), + expectation!(gr_send_wgas_per_byte), + expectation!(gr_send_init), + expectation!(gr_send_push), + expectation!(gr_send_push_per_byte), + expectation!(gr_send_commit), + expectation!(gr_send_commit_wgas), + expectation!(gr_reservation_send), + expectation!(gr_reservation_send_per_byte), + expectation!(gr_reservation_send_commit), + expectation!(gr_reply_commit), + expectation!(gr_reply_commit_wgas), + expectation!(gr_reservation_reply), + expectation!(gr_reservation_reply_per_byte), + expectation!(gr_reservation_reply_commit), + expectation!(gr_reply_push), + expectation!(gr_reply), + expectation!(gr_reply_per_byte), + expectation!(gr_reply_wgas), + expectation!(gr_reply_wgas_per_byte), + expectation!(gr_reply_push_per_byte), + expectation!(gr_reply_to), + expectation!(gr_signal_code), + expectation!(gr_signal_from), + expectation!(gr_reply_input), + expectation!(gr_reply_input_wgas), + expectation!(gr_reply_push_input), + expectation!(gr_reply_push_input_per_byte), + expectation!(gr_send_input), + expectation!(gr_send_input_wgas), + expectation!(gr_send_push_input), + expectation!(gr_send_push_input_per_byte), + expectation!(gr_debug), + expectation!(gr_debug_per_byte), + expectation!(gr_reply_code), + expectation!(gr_exit), + expectation!(gr_leave), + expectation!(gr_wait), + expectation!(gr_wait_for), + expectation!(gr_wait_up_to), + expectation!(gr_wake), + expectation!(gr_create_program), + expectation!(gr_create_program_payload_per_byte), + expectation!(gr_create_program_salt_per_byte), + expectation!(gr_create_program_wgas), + expectation!(gr_create_program_wgas_payload_per_byte), + expectation!(gr_create_program_wgas_salt_per_byte), + ]; + + check_expectations(&expectations) +} + +/// Check that the lazy-pages costs are within the expected range +pub fn check_lazy_pages_costs( + lazy_pages_costs: LazyPagesCosts, + expected_lazy_pages_costs: LazyPagesCosts, +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + lazy_pages_costs.$inst_name.cost_for_one(), + expected_lazy_pages_costs.$inst_name.cost_for_one(), + PAGES_SPREAD, + stringify!($inst_name), + ) + }; + } + + let expectations = vec![ + expectation!(signal_read), + expectation!(signal_write), + expectation!(signal_write_after_read), + expectation!(host_func_read), + expectation!(host_func_write), + expectation!(host_func_write_after_read), + expectation!(load_page_storage_data), + ]; + + check_expectations(&expectations) +} + +/// Memory pages access costs. +pub struct PagesCosts { + pub load_page_data: CostOf, + pub upload_page_data: CostOf, + pub mem_grow: CostOf, + pub mem_grow_per_page: CostOf, + pub parachain_read_heuristic: CostOf, +} + +impl From> for PagesCosts { + fn from(val: MemoryWeights) -> Self { + Self { + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), + } + } +} + +/// Check that the pages costs are within the expected range +pub fn check_pages_costs( + page_costs: PagesCosts, + expected_page_costs: PagesCosts, +) -> Result<(), Vec> { + macro_rules! expectation { + ($inst_name:ident) => { + WeightExpectation::new( + page_costs.$inst_name.cost_for_one(), + expected_page_costs.$inst_name.cost_for_one(), + PAGES_SPREAD, + stringify!($inst_name), + ) + }; + } + + let expectations = vec![ + expectation!(load_page_data), + expectation!(upload_page_data), + expectation!(mem_grow), + expectation!(mem_grow_per_page), + expectation!(parachain_read_heuristic), + ]; + + check_expectations(&expectations) +} + #[cfg(feature = "dev")] #[test] fn bridge_storages_have_correct_prefixes() { From f69e521acb8ed6321bc4caf25f4ed82ed5925cd7 Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Tue, 24 Sep 2024 12:31:58 +0200 Subject: [PATCH 3/7] fixed source file structure --- runtime/vara/src/tests.rs | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/runtime/vara/src/tests.rs b/runtime/vara/src/tests.rs index a9f88b0b5c6..061e03fa809 100644 --- a/runtime/vara/src/tests.rs +++ b/runtime/vara/src/tests.rs @@ -32,7 +32,7 @@ const INSTRUCTIONS_SPREAD: u8 = 50; const SYSCALL_SPREAD: u8 = 10; const PAGES_SPREAD: u8 = 10; -#[derive(Clone, Copy)] +/// Structure to hold weight expectation struct WeightExpectation { weight: u64, expected: u64, @@ -81,8 +81,29 @@ fn check_expectations(expectations: &[WeightExpectation]) -> Result<(), Vec, + pub upload_page_data: CostOf, + pub mem_grow: CostOf, + pub mem_grow_per_page: CostOf, + pub parachain_read_heuristic: CostOf, +} + +impl From> for PagesCosts { + fn from(val: MemoryWeights) -> Self { + Self { + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), + } + } +} + /// Check that the weights of instructions are within the expected range -pub fn check_instructions_weights( +fn check_instructions_weights( weights: InstructionWeights, expected: InstructionWeights, ) -> Result<(), Vec> { @@ -191,7 +212,7 @@ pub fn check_instructions_weights( } /// Check that the weights of syscalls are within the expected range -pub fn check_syscall_weights( +fn check_syscall_weights( weights: SyscallWeights, expected: SyscallWeights, ) -> Result<(), Vec> { @@ -283,7 +304,7 @@ pub fn check_syscall_weights( } /// Check that the lazy-pages costs are within the expected range -pub fn check_lazy_pages_costs( +fn check_lazy_pages_costs( lazy_pages_costs: LazyPagesCosts, expected_lazy_pages_costs: LazyPagesCosts, ) -> Result<(), Vec> { @@ -311,29 +332,8 @@ pub fn check_lazy_pages_costs( check_expectations(&expectations) } -/// Memory pages access costs. -pub struct PagesCosts { - pub load_page_data: CostOf, - pub upload_page_data: CostOf, - pub mem_grow: CostOf, - pub mem_grow_per_page: CostOf, - pub parachain_read_heuristic: CostOf, -} - -impl From> for PagesCosts { - fn from(val: MemoryWeights) -> Self { - Self { - load_page_data: val.load_page_data.ref_time().into(), - upload_page_data: val.upload_page_data.ref_time().into(), - mem_grow: val.mem_grow.ref_time().into(), - mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), - parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), - } - } -} - /// Check that the pages costs are within the expected range -pub fn check_pages_costs( +fn check_pages_costs( page_costs: PagesCosts, expected_page_costs: PagesCosts, ) -> Result<(), Vec> { From e79d1fae57e5d493711751ae2b424ffbf3456b54 Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Tue, 5 Nov 2024 12:30:24 +0100 Subject: [PATCH 4/7] post-review changes: added test for weights count --- core/src/costs.rs | 10 ++ core/src/gas_metering/schedule.rs | 5 + pallets/gear/src/schedule.rs | 5 + runtime/vara/src/tests.rs | 270 ++++++++++++++++++++++++++---- 4 files changed, 258 insertions(+), 32 deletions(-) diff --git a/core/src/costs.rs b/core/src/costs.rs index 58c6dae5629..81f1e5cc1ec 100644 --- a/core/src/costs.rs +++ b/core/src/costs.rs @@ -519,6 +519,16 @@ pub struct LazyPagesCosts { pub host_func_write_after_read: CostOf, /// Loading page data from storage cost. pub load_page_storage_data: CostOf, + /// Loading from storage and moving it in program memory cost. + pub load_page_data: CostOf, + /// Uploading page data to storage cost. + pub upload_page_data: CostOf, + /// Memory grow cost. + pub mem_grow: CostOf, + /// Memory grow per page cost. + pub mem_grow_per_page: CostOf, + /// Parachain read heuristic cost. + pub parachain_read_heuristic: CostOf, } /// Holding in storages rent costs. diff --git a/core/src/gas_metering/schedule.rs b/core/src/gas_metering/schedule.rs index 24b156a3b7b..85e5a2fc12b 100644 --- a/core/src/gas_metering/schedule.rs +++ b/core/src/gas_metering/schedule.rs @@ -1223,6 +1223,11 @@ impl From for LazyPagesCosts { .saturating_add(val.parachain_read_heuristic) .ref_time() .into(), + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), } } } diff --git a/pallets/gear/src/schedule.rs b/pallets/gear/src/schedule.rs index a474ddc620c..093752f75ab 100644 --- a/pallets/gear/src/schedule.rs +++ b/pallets/gear/src/schedule.rs @@ -1331,6 +1331,11 @@ impl From> for LazyPagesCosts { .saturating_add(val.parachain_read_heuristic) .ref_time() .into(), + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), } } } diff --git a/runtime/vara/src/tests.rs b/runtime/vara/src/tests.rs index 061e03fa809..13289b7bebf 100644 --- a/runtime/vara/src/tests.rs +++ b/runtime/vara/src/tests.rs @@ -18,16 +18,17 @@ use super::*; use crate::Runtime; -use frame_support::{dispatch::GetDispatchInfo, traits::StorageInstance}; + +use frame_support::dispatch::GetDispatchInfo; use frame_system::limits::WeightsPerClass; -use gear_core::{ - costs::{CostOf, LazyPagesCosts}, - pages::GearPagesAmount, -}; +use gear_core::costs::LazyPagesCosts; use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; use pallet_staking::WeightInfo as _; use sp_runtime::AccountId32; +#[cfg(feature = "dev")] +use frame_support::traits::StorageInstance; + const INSTRUCTIONS_SPREAD: u8 = 50; const SYSCALL_SPREAD: u8 = 10; const PAGES_SPREAD: u8 = 10; @@ -62,7 +63,7 @@ impl WeightExpectation { } } -fn check_expectations(expectations: &[WeightExpectation]) -> Result<(), Vec> { +fn check_expectations(expectations: &[WeightExpectation]) -> Result> { let errors = expectations .iter() .filter_map(|expectation| { @@ -75,38 +76,237 @@ fn check_expectations(expectations: &[WeightExpectation]) -> Result<(), Vec>(); if errors.is_empty() { - Ok(()) + Ok(expectations.iter().count()) } else { Err(errors) } } -/// Memory pages access costs. -struct PagesCosts { - pub load_page_data: CostOf, - pub upload_page_data: CostOf, - pub mem_grow: CostOf, - pub mem_grow_per_page: CostOf, - pub parachain_read_heuristic: CostOf, +fn expected_instructions_weights_count() -> usize { + let InstructionWeights { + i64const: _, + i64load: _, + i32load: _, + i64store: _, + i32store: _, + select: _, + r#if: _, + br: _, + br_if: _, + br_table: _, + br_table_per_entry: _, + call: _, + call_indirect: _, + call_indirect_per_param: _, + call_per_local: _, + local_get: _, + local_set: _, + local_tee: _, + global_get: _, + global_set: _, + memory_current: _, + i64clz: _, + i32clz: _, + i64ctz: _, + i32ctz: _, + i64popcnt: _, + i32popcnt: _, + i64eqz: _, + i32eqz: _, + i32extend8s: _, + i32extend16s: _, + i64extend8s: _, + i64extend16s: _, + i64extend32s: _, + i64extendsi32: _, + i64extendui32: _, + i32wrapi64: _, + i64eq: _, + i32eq: _, + i64ne: _, + i32ne: _, + i64lts: _, + i32lts: _, + i64ltu: _, + i32ltu: _, + i64gts: _, + i32gts: _, + i64gtu: _, + i32gtu: _, + i64les: _, + i32les: _, + i64leu: _, + i32leu: _, + i64ges: _, + i32ges: _, + i64geu: _, + i32geu: _, + i64add: _, + i32add: _, + i64sub: _, + i32sub: _, + i64mul: _, + i32mul: _, + i64divs: _, + i32divs: _, + i64divu: _, + i32divu: _, + i64rems: _, + i32rems: _, + i64remu: _, + i32remu: _, + i64and: _, + i32and: _, + i64or: _, + i32or: _, + i64xor: _, + i32xor: _, + i64shl: _, + i32shl: _, + i64shrs: _, + i32shrs: _, + i64shru: _, + i32shru: _, + i64rotl: _, + i32rotl: _, + i64rotr: _, + i32rotr: _, + version: _, + _phantom: _, + } = InstructionWeights::::default(); + + // total number of instructions + 87 } -impl From> for PagesCosts { - fn from(val: MemoryWeights) -> Self { - Self { - load_page_data: val.load_page_data.ref_time().into(), - upload_page_data: val.upload_page_data.ref_time().into(), - mem_grow: val.mem_grow.ref_time().into(), - mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), - parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), - } - } +fn expected_syscall_weights_count() -> usize { + let SyscallWeights { + alloc: _, + free: _, + free_range: _, + free_range_per_page: _, + gr_reserve_gas: _, + gr_unreserve_gas: _, + gr_system_reserve_gas: _, + gr_gas_available: _, + gr_message_id: _, + gr_program_id: _, + gr_source: _, + gr_value: _, + gr_value_available: _, + gr_size: _, + gr_read: _, + gr_read_per_byte: _, + gr_env_vars: _, + gr_block_height: _, + gr_block_timestamp: _, + gr_random: _, + gr_reply_deposit: _, + gr_send: _, + gr_send_per_byte: _, + gr_send_wgas: _, + gr_send_wgas_per_byte: _, + gr_send_init: _, + gr_send_push: _, + gr_send_push_per_byte: _, + gr_send_commit: _, + gr_send_commit_wgas: _, + gr_reservation_send: _, + gr_reservation_send_per_byte: _, + gr_reservation_send_commit: _, + gr_reply_commit: _, + gr_reply_commit_wgas: _, + gr_reservation_reply: _, + gr_reservation_reply_per_byte: _, + gr_reservation_reply_commit: _, + gr_reply_push: _, + gr_reply: _, + gr_reply_per_byte: _, + gr_reply_wgas: _, + gr_reply_wgas_per_byte: _, + gr_reply_push_per_byte: _, + gr_reply_to: _, + gr_signal_code: _, + gr_signal_from: _, + gr_reply_input: _, + gr_reply_input_wgas: _, + gr_reply_push_input: _, + gr_reply_push_input_per_byte: _, + gr_send_input: _, + gr_send_input_wgas: _, + gr_send_push_input: _, + gr_send_push_input_per_byte: _, + gr_debug: _, + gr_debug_per_byte: _, + gr_reply_code: _, + gr_exit: _, + gr_leave: _, + gr_wait: _, + gr_wait_for: _, + gr_wait_up_to: _, + gr_wake: _, + gr_create_program: _, + gr_create_program_payload_per_byte: _, + gr_create_program_salt_per_byte: _, + gr_create_program_wgas: _, + gr_create_program_wgas_payload_per_byte: _, + gr_create_program_wgas_salt_per_byte: _, + _phantom: __phantom, + } = SyscallWeights::::default(); + + // total number of syscalls + 70 +} + +fn expected_pages_costs_count() -> usize { + let LazyPagesCosts { + // Fields for lazy pages costs + signal_read: _, + signal_write: _, + signal_write_after_read: _, + host_func_read: _, + host_func_write: _, + host_func_write_after_read: _, + load_page_storage_data: _, + // Fields for pages costs + load_page_data: _, + upload_page_data: _, + mem_grow: _, + mem_grow_per_page: _, + parachain_read_heuristic: _, + } = MemoryWeights::::default().into(); + + // total number of lazy pages costs + 5 +} + +fn expected_lazy_pages_costs_count() -> usize { + let LazyPagesCosts { + // Fields for lazy pages costs + signal_read: _, + signal_write: _, + signal_write_after_read: _, + host_func_read: _, + host_func_write: _, + host_func_write_after_read: _, + load_page_storage_data: _, + // Fields for pages costs + load_page_data: _, + upload_page_data: _, + mem_grow: _, + mem_grow_per_page: _, + parachain_read_heuristic: _, + } = MemoryWeights::::default().into(); + + // total number of lazy pages costs + 7 } /// Check that the weights of instructions are within the expected range fn check_instructions_weights( weights: InstructionWeights, expected: InstructionWeights, -) -> Result<(), Vec> { +) -> Result> { macro_rules! expectation { ($inst_name:ident) => { WeightExpectation::new( @@ -215,7 +415,7 @@ fn check_instructions_weights( fn check_syscall_weights( weights: SyscallWeights, expected: SyscallWeights, -) -> Result<(), Vec> { +) -> Result> { macro_rules! expectation { ($inst_name:ident) => { WeightExpectation::new( @@ -307,7 +507,7 @@ fn check_syscall_weights( fn check_lazy_pages_costs( lazy_pages_costs: LazyPagesCosts, expected_lazy_pages_costs: LazyPagesCosts, -) -> Result<(), Vec> { +) -> Result> { macro_rules! expectation { ($inst_name:ident) => { WeightExpectation::new( @@ -334,9 +534,9 @@ fn check_lazy_pages_costs( /// Check that the pages costs are within the expected range fn check_pages_costs( - page_costs: PagesCosts, - expected_page_costs: PagesCosts, -) -> Result<(), Vec> { + page_costs: LazyPagesCosts, + expected_page_costs: LazyPagesCosts, +) -> Result> { macro_rules! expectation { ($inst_name:ident) => { WeightExpectation::new( @@ -557,6 +757,7 @@ fn instruction_weights_heuristics_test() { let result = check_instructions_weights(weights, expected_weights); assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_instructions_weights_count()); } #[test] @@ -640,23 +841,26 @@ fn syscall_weights_test() { let result = check_syscall_weights(weights, expected); assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_syscall_weights_count()); } #[test] fn page_costs_heuristic_test() { - let page_costs: PagesCosts = MemoryWeights::::default().into(); + let page_costs: LazyPagesCosts = MemoryWeights::::default().into(); - let expected_page_costs = PagesCosts { + let expected_page_costs = LazyPagesCosts { load_page_data: 9_000_000.into(), upload_page_data: 105_000_000.into(), mem_grow: 800_000.into(), mem_grow_per_page: 0.into(), parachain_read_heuristic: 0.into(), + ..Default::default() }; let result = check_pages_costs(page_costs, expected_page_costs); assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_pages_costs_count()); } #[test] @@ -671,11 +875,13 @@ fn lazy_page_costs_heuristic_test() { host_func_write: 137_000_000.into(), host_func_write_after_read: 112_000_000.into(), load_page_storage_data: 9_000_000.into(), + ..Default::default() }; let result = check_lazy_pages_costs(lazy_pages_costs, expected_lazy_pages_costs); assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_lazy_pages_costs_count()); } /// Check that it is not possible to write/change memory pages too cheaply, From e825e990d53d5afc22bb735a044b22e88c5ad85e Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Tue, 5 Nov 2024 16:49:25 +0100 Subject: [PATCH 5/7] post-review: code structure fix --- runtime/vara/src/tests/mod.rs | 376 ++++++++++++++++++ runtime/vara/src/{tests.rs => tests/utils.rs} | 372 +---------------- 2 files changed, 388 insertions(+), 360 deletions(-) create mode 100644 runtime/vara/src/tests/mod.rs rename runtime/vara/src/{tests.rs => tests/utils.rs} (56%) diff --git a/runtime/vara/src/tests/mod.rs b/runtime/vara/src/tests/mod.rs new file mode 100644 index 00000000000..49d5b5dea86 --- /dev/null +++ b/runtime/vara/src/tests/mod.rs @@ -0,0 +1,376 @@ +// This file is part of Gear. + +// Copyright (C) 2021-2024 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Weight tests for the runtime. + +use super::*; +use crate::Runtime; + +use frame_support::dispatch::GetDispatchInfo; +use frame_system::limits::WeightsPerClass; +use gear_core::costs::LazyPagesCosts; +use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; +use pallet_staking::WeightInfo as _; +use sp_runtime::AccountId32; + +#[cfg(feature = "dev")] +use frame_support::traits::StorageInstance; + +mod utils; +use utils::*; + +#[cfg(feature = "dev")] +#[test] +fn bridge_storages_have_correct_prefixes() { + // # SAFETY: Do not change storage prefixes without total bridge re-deploy. + const PALLET_PREFIX: &str = "GearEthBridge"; + + assert_eq!( + pallet_gear_eth_bridge::AuthoritySetHashPrefix::::pallet_prefix(), + PALLET_PREFIX + ); + assert_eq!( + pallet_gear_eth_bridge::QueueMerkleRootPrefix::::pallet_prefix(), + PALLET_PREFIX + ); + + assert_eq!( + pallet_gear_eth_bridge::AuthoritySetHashPrefix::::STORAGE_PREFIX, + "AuthoritySetHash" + ); + assert_eq!( + pallet_gear_eth_bridge::QueueMerkleRootPrefix::::STORAGE_PREFIX, + "QueueMerkleRoot" + ); +} + +#[cfg(feature = "dev")] +#[test] +fn bridge_session_timer_is_correct() { + assert_eq!( + ::SessionsPerEra::get(), + ::SessionsPerEra::get() + ); + + // # SAFETY: Do not change staking's SessionsPerEra parameter without + // making sure of correct integration with already running network. + // + // Change of the param will require migrating `pallet-gear-eth-bridge`'s + // `ClearTimer` (or any actual time- or epoch- dependent entity) and + // corresponding constant or even total bridge re-deploy. + assert_eq!( + ::SessionsPerEra::get(), + 6 + ); +} + +#[test] +fn payout_stakers_fits_in_block() { + let expected_weight = + ::WeightInfo::payout_stakers_alive_staked( + ::MaxExposurePageSize::get(), + ); + + let call: ::RuntimeCall = + RuntimeCall::Staking(pallet_staking::Call::payout_stakers { + validator_stash: AccountId32::new(Default::default()), + era: Default::default(), + }); + + let dispatch_info = call.get_dispatch_info(); + + assert_eq!(dispatch_info.class, DispatchClass::Normal); + assert_eq!(dispatch_info.weight, expected_weight); + + let block_weights = ::BlockWeights::get(); + + let normal_class_weights: WeightsPerClass = + block_weights.per_class.get(DispatchClass::Normal).clone(); + + let normal_ref_time = normal_class_weights + .max_extrinsic + .unwrap_or(Weight::MAX) + .ref_time(); + let base_weight = normal_class_weights.base_extrinsic.ref_time(); + + assert!(normal_ref_time - base_weight > expected_weight.ref_time()); +} + +#[test] +fn normal_dispatch_length_suits_minimal() { + const MB: u32 = 1024 * 1024; + + let block_length = ::BlockLength::get(); + + // Normal dispatch class is bigger than 2 MB. + assert!(*block_length.max.get(DispatchClass::Normal) > 2 * MB); + + // Others are on maximum. + assert_eq!(*block_length.max.get(DispatchClass::Operational), 5 * MB); + assert_eq!(*block_length.max.get(DispatchClass::Mandatory), 5 * MB); +} + +#[test] +fn instruction_weights_heuristics_test() { + let weights = InstructionWeights::::default(); + + let expected_weights = InstructionWeights { + version: 0, + _phantom: core::marker::PhantomData, + + i64const: 160, + i64load: 5_800, + i32load: 8_000, + i64store: 10_000, + i32store: 20_000, + select: 7_100, + r#if: 8_000, + br: 3_300, + br_if: 6_000, + br_table: 10_900, + br_table_per_entry: 150, + + call: 4_900, + call_per_local: 0, + call_indirect: 22_100, + call_indirect_per_param: 1_000, + + local_get: 900, + local_set: 1_900, + local_tee: 2_500, + global_get: 700, + global_set: 1_000, + memory_current: 14_200, + + i64clz: 400, + i32clz: 300, + i64ctz: 400, + i32ctz: 250, + i64popcnt: 450, + i32popcnt: 350, + i64eqz: 1_300, + i32eqz: 1_200, + i32extend8s: 200, + i32extend16s: 200, + i64extend8s: 400, + i64extend16s: 400, + i64extend32s: 400, + i64extendsi32: 200, + i64extendui32: 200, + i32wrapi64: 200, + i64eq: 1_800, + i32eq: 1_100, + i64ne: 1_700, + i32ne: 1_000, + + i64lts: 1_200, + i32lts: 1_000, + i64ltu: 1_200, + i32ltu: 1_000, + i64gts: 1_200, + i32gts: 1_000, + i64gtu: 1_900, + i32gtu: 1_000, + i64les: 1_900, + i32les: 1_000, + i64leu: 1_200, + i32leu: 1_000, + + i64ges: 1_300, + i32ges: 1_000, + i64geu: 1_300, + i32geu: 1_000, + i64add: 1_300, + i32add: 500, + i64sub: 1_300, + i32sub: 500, + i64mul: 2_000, + i32mul: 1_000, + i64divs: 3_500, + i32divs: 3_500, + + i64divu: 3_500, + i32divu: 3_500, + i64rems: 18_000, + i32rems: 15_000, + i64remu: 3_500, + i32remu: 3_500, + i64and: 1_000, + i32and: 500, + i64or: 1_000, + i32or: 500, + i64xor: 1_000, + i32xor: 500, + + i64shl: 1_000, + i32shl: 400, + i64shrs: 1_000, + i32shrs: 250, + i64shru: 1_000, + i32shru: 400, + i64rotl: 750, + i32rotl: 400, + i64rotr: 1_000, + i32rotr: 300, + }; + + let result = check_instructions_weights(weights, expected_weights); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_instructions_weights_count()); +} + +#[test] +fn syscall_weights_test() { + let weights = SyscallWeights::::default(); + + let expected = SyscallWeights { + alloc: 1_500_000.into(), + free: 900_000.into(), + free_range: 900_000.into(), + free_range_per_page: 40_000.into(), + gr_reserve_gas: 2_300_000.into(), + gr_unreserve_gas: 2_200_000.into(), + gr_system_reserve_gas: 1_200_000.into(), + gr_gas_available: 1_000_000.into(), + gr_message_id: 1_000_000.into(), + gr_program_id: 1_000_000.into(), + gr_source: 1_000_000.into(), + gr_value: 1_000_000.into(), + gr_value_available: 1_000_000.into(), + gr_size: 1_000_000.into(), + gr_read: 1_900_000.into(), + gr_read_per_byte: 200.into(), + gr_env_vars: 1_200_000.into(), + gr_block_height: 1_000_000.into(), + gr_block_timestamp: 1_000_000.into(), + gr_random: 1_900_000.into(), + gr_reply_deposit: 4_900_000.into(), + gr_send: 3_200_000.into(), + gr_send_per_byte: 500.into(), + gr_send_wgas: 3_300_000.into(), + gr_send_wgas_per_byte: 500.into(), + gr_send_init: 1_200_000.into(), + gr_send_push: 2_000_000.into(), + gr_send_push_per_byte: 500.into(), + gr_send_commit: 2_700_000.into(), + gr_send_commit_wgas: 2_700_000.into(), + gr_reservation_send: 3_400_000.into(), + gr_reservation_send_per_byte: 500.into(), + gr_reservation_send_commit: 2_900_000.into(), + gr_reply_commit: 12_000_000.into(), + gr_reply_commit_wgas: 12_000_000.into(), + gr_reservation_reply: 8_500_000.into(), + gr_reservation_reply_per_byte: 675_000.into(), + gr_reservation_reply_commit: 8_000_000.into(), + gr_reply_push: 1_700_000.into(), + gr_reply: 12_500_000.into(), + gr_reply_per_byte: 650.into(), + gr_reply_wgas: 12_500_000.into(), + gr_reply_wgas_per_byte: 650.into(), + gr_reply_push_per_byte: 640.into(), + gr_reply_to: 1_000_000.into(), + gr_signal_code: 1_000_000.into(), + gr_signal_from: 1_000_000.into(), + gr_reply_input: 20_000_000.into(), + gr_reply_input_wgas: 30_000_000.into(), + gr_reply_push_input: 1_200_000.into(), + gr_reply_push_input_per_byte: 110.into(), + gr_send_input: 3_100_000.into(), + gr_send_input_wgas: 3_100_000.into(), + gr_send_push_input: 1_500_000.into(), + gr_send_push_input_per_byte: 150.into(), + gr_debug: 1_200_000.into(), + gr_debug_per_byte: 500.into(), + gr_reply_code: 1_000_000.into(), + gr_exit: 18_000_000.into(), + gr_leave: 14_000_000.into(), + gr_wait: 14_000_000.into(), + gr_wait_for: 14_000_000.into(), + gr_wait_up_to: 14_500_000.into(), + gr_wake: 3_300_000.into(), + gr_create_program: 4_100_000.into(), + gr_create_program_payload_per_byte: 120.into(), + gr_create_program_salt_per_byte: 1_400.into(), + gr_create_program_wgas: 4_100_000.into(), + gr_create_program_wgas_payload_per_byte: 120.into(), + gr_create_program_wgas_salt_per_byte: 1_400.into(), + _phantom: Default::default(), + }; + + let result = check_syscall_weights(weights, expected); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_syscall_weights_count()); +} + +#[test] +fn page_costs_heuristic_test() { + let page_costs: LazyPagesCosts = MemoryWeights::::default().into(); + + let expected_page_costs = LazyPagesCosts { + load_page_data: 9_000_000.into(), + upload_page_data: 105_000_000.into(), + mem_grow: 800_000.into(), + mem_grow_per_page: 0.into(), + parachain_read_heuristic: 0.into(), + ..Default::default() + }; + + let result = check_pages_costs(page_costs, expected_page_costs); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_pages_costs_count()); +} + +#[test] +fn lazy_page_costs_heuristic_test() { + let lazy_pages_costs: LazyPagesCosts = MemoryWeights::::default().into(); + + let expected_lazy_pages_costs = LazyPagesCosts { + signal_read: 28_000_000.into(), + signal_write: 138_000_000.into(), + signal_write_after_read: 112_000_000.into(), + host_func_read: 29_000_000.into(), + host_func_write: 137_000_000.into(), + host_func_write_after_read: 112_000_000.into(), + load_page_storage_data: 9_000_000.into(), + ..Default::default() + }; + + let result = check_lazy_pages_costs(lazy_pages_costs, expected_lazy_pages_costs); + + assert!(result.is_ok(), "{:#?}", result.err().unwrap()); + assert_eq!(result.unwrap(), expected_lazy_pages_costs_count()); +} + +/// Check that it is not possible to write/change memory pages too cheaply, +/// because this may cause runtime heap memory overflow. +#[test] +fn write_is_not_too_cheap() { + let costs: LazyPagesCosts = MemoryWeights::::default().into(); + let cheapest_write = u64::MAX + .min(costs.signal_write.cost_for_one()) + .min(costs.signal_read.cost_for_one() + costs.signal_write_after_read.cost_for_one()) + .min(costs.host_func_write.cost_for_one()) + .min(costs.host_func_read.cost_for_one() + costs.host_func_write_after_read.cost_for_one()); + + let block_max_gas = 3 * 10 ^ 12; // 3 seconds + let runtime_heap_size_in_wasm_pages = 0x4000; // 1GB + assert!((block_max_gas / cheapest_write) < runtime_heap_size_in_wasm_pages); +} diff --git a/runtime/vara/src/tests.rs b/runtime/vara/src/tests/utils.rs similarity index 56% rename from runtime/vara/src/tests.rs rename to runtime/vara/src/tests/utils.rs index 13289b7bebf..b30b776438e 100644 --- a/runtime/vara/src/tests.rs +++ b/runtime/vara/src/tests/utils.rs @@ -19,22 +19,15 @@ use super::*; use crate::Runtime; -use frame_support::dispatch::GetDispatchInfo; -use frame_system::limits::WeightsPerClass; use gear_core::costs::LazyPagesCosts; use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; -use pallet_staking::WeightInfo as _; -use sp_runtime::AccountId32; - -#[cfg(feature = "dev")] -use frame_support::traits::StorageInstance; const INSTRUCTIONS_SPREAD: u8 = 50; const SYSCALL_SPREAD: u8 = 10; const PAGES_SPREAD: u8 = 10; /// Structure to hold weight expectation -struct WeightExpectation { +pub(super) struct WeightExpectation { weight: u64, expected: u64, spread: u8, @@ -42,7 +35,7 @@ struct WeightExpectation { } impl WeightExpectation { - fn new(weight: u64, expected: u64, spread: u8, name: &'static str) -> Self { + pub(super) fn new(weight: u64, expected: u64, spread: u8, name: &'static str) -> Self { Self { weight, expected, @@ -51,7 +44,7 @@ impl WeightExpectation { } } - fn check(&self) -> Result<(), String> { + pub(super) fn check(&self) -> Result<(), String> { let left = self.expected - self.expected * self.spread as u64 / 100; let right = self.expected + self.expected * self.spread as u64 / 100; @@ -63,7 +56,7 @@ impl WeightExpectation { } } -fn check_expectations(expectations: &[WeightExpectation]) -> Result> { +pub(super) fn check_expectations(expectations: &[WeightExpectation]) -> Result> { let errors = expectations .iter() .filter_map(|expectation| { @@ -82,7 +75,7 @@ fn check_expectations(expectations: &[WeightExpectation]) -> Result usize { +pub(super) fn expected_instructions_weights_count() -> usize { let InstructionWeights { i64const: _, i64load: _, @@ -179,7 +172,7 @@ fn expected_instructions_weights_count() -> usize { 87 } -fn expected_syscall_weights_count() -> usize { +pub(super) fn expected_syscall_weights_count() -> usize { let SyscallWeights { alloc: _, free: _, @@ -258,7 +251,7 @@ fn expected_syscall_weights_count() -> usize { 70 } -fn expected_pages_costs_count() -> usize { +pub(super) fn expected_pages_costs_count() -> usize { let LazyPagesCosts { // Fields for lazy pages costs signal_read: _, @@ -280,7 +273,7 @@ fn expected_pages_costs_count() -> usize { 5 } -fn expected_lazy_pages_costs_count() -> usize { +pub(super) fn expected_lazy_pages_costs_count() -> usize { let LazyPagesCosts { // Fields for lazy pages costs signal_read: _, @@ -303,7 +296,7 @@ fn expected_lazy_pages_costs_count() -> usize { } /// Check that the weights of instructions are within the expected range -fn check_instructions_weights( +pub(super) fn check_instructions_weights( weights: InstructionWeights, expected: InstructionWeights, ) -> Result> { @@ -412,7 +405,7 @@ fn check_instructions_weights( } /// Check that the weights of syscalls are within the expected range -fn check_syscall_weights( +pub(super) fn check_syscall_weights( weights: SyscallWeights, expected: SyscallWeights, ) -> Result> { @@ -504,7 +497,7 @@ fn check_syscall_weights( } /// Check that the lazy-pages costs are within the expected range -fn check_lazy_pages_costs( +pub(super) fn check_lazy_pages_costs( lazy_pages_costs: LazyPagesCosts, expected_lazy_pages_costs: LazyPagesCosts, ) -> Result> { @@ -533,7 +526,7 @@ fn check_lazy_pages_costs( } /// Check that the pages costs are within the expected range -fn check_pages_costs( +pub(super) fn check_pages_costs( page_costs: LazyPagesCosts, expected_page_costs: LazyPagesCosts, ) -> Result> { @@ -558,344 +551,3 @@ fn check_pages_costs( check_expectations(&expectations) } - -#[cfg(feature = "dev")] -#[test] -fn bridge_storages_have_correct_prefixes() { - // # SAFETY: Do not change storage prefixes without total bridge re-deploy. - const PALLET_PREFIX: &str = "GearEthBridge"; - - assert_eq!( - pallet_gear_eth_bridge::AuthoritySetHashPrefix::::pallet_prefix(), - PALLET_PREFIX - ); - assert_eq!( - pallet_gear_eth_bridge::QueueMerkleRootPrefix::::pallet_prefix(), - PALLET_PREFIX - ); - - assert_eq!( - pallet_gear_eth_bridge::AuthoritySetHashPrefix::::STORAGE_PREFIX, - "AuthoritySetHash" - ); - assert_eq!( - pallet_gear_eth_bridge::QueueMerkleRootPrefix::::STORAGE_PREFIX, - "QueueMerkleRoot" - ); -} - -#[cfg(feature = "dev")] -#[test] -fn bridge_session_timer_is_correct() { - assert_eq!( - ::SessionsPerEra::get(), - ::SessionsPerEra::get() - ); - - // # SAFETY: Do not change staking's SessionsPerEra parameter without - // making sure of correct integration with already running network. - // - // Change of the param will require migrating `pallet-gear-eth-bridge`'s - // `ClearTimer` (or any actual time- or epoch- dependent entity) and - // corresponding constant or even total bridge re-deploy. - assert_eq!( - ::SessionsPerEra::get(), - 6 - ); -} - -#[test] -fn payout_stakers_fits_in_block() { - let expected_weight = - ::WeightInfo::payout_stakers_alive_staked( - ::MaxExposurePageSize::get(), - ); - - let call: ::RuntimeCall = - RuntimeCall::Staking(pallet_staking::Call::payout_stakers { - validator_stash: AccountId32::new(Default::default()), - era: Default::default(), - }); - - let dispatch_info = call.get_dispatch_info(); - - assert_eq!(dispatch_info.class, DispatchClass::Normal); - assert_eq!(dispatch_info.weight, expected_weight); - - let block_weights = ::BlockWeights::get(); - - let normal_class_weights: WeightsPerClass = - block_weights.per_class.get(DispatchClass::Normal).clone(); - - let normal_ref_time = normal_class_weights - .max_extrinsic - .unwrap_or(Weight::MAX) - .ref_time(); - let base_weight = normal_class_weights.base_extrinsic.ref_time(); - - assert!(normal_ref_time - base_weight > expected_weight.ref_time()); -} - -#[test] -fn normal_dispatch_length_suits_minimal() { - const MB: u32 = 1024 * 1024; - - let block_length = ::BlockLength::get(); - - // Normal dispatch class is bigger than 2 MB. - assert!(*block_length.max.get(DispatchClass::Normal) > 2 * MB); - - // Others are on maximum. - assert_eq!(*block_length.max.get(DispatchClass::Operational), 5 * MB); - assert_eq!(*block_length.max.get(DispatchClass::Mandatory), 5 * MB); -} - -#[test] -fn instruction_weights_heuristics_test() { - let weights = InstructionWeights::::default(); - - let expected_weights = InstructionWeights { - version: 0, - _phantom: core::marker::PhantomData, - - i64const: 160, - i64load: 5_800, - i32load: 8_000, - i64store: 10_000, - i32store: 20_000, - select: 7_100, - r#if: 8_000, - br: 3_300, - br_if: 6_000, - br_table: 10_900, - br_table_per_entry: 150, - - call: 4_900, - call_per_local: 0, - call_indirect: 22_100, - call_indirect_per_param: 1_000, - - local_get: 900, - local_set: 1_900, - local_tee: 2_500, - global_get: 700, - global_set: 1_000, - memory_current: 14_200, - - i64clz: 400, - i32clz: 300, - i64ctz: 400, - i32ctz: 250, - i64popcnt: 450, - i32popcnt: 350, - i64eqz: 1_300, - i32eqz: 1_200, - i32extend8s: 200, - i32extend16s: 200, - i64extend8s: 400, - i64extend16s: 400, - i64extend32s: 400, - i64extendsi32: 200, - i64extendui32: 200, - i32wrapi64: 200, - i64eq: 1_800, - i32eq: 1_100, - i64ne: 1_700, - i32ne: 1_000, - - i64lts: 1_200, - i32lts: 1_000, - i64ltu: 1_200, - i32ltu: 1_000, - i64gts: 1_200, - i32gts: 1_000, - i64gtu: 1_900, - i32gtu: 1_000, - i64les: 1_900, - i32les: 1_000, - i64leu: 1_200, - i32leu: 1_000, - - i64ges: 1_300, - i32ges: 1_000, - i64geu: 1_300, - i32geu: 1_000, - i64add: 1_300, - i32add: 500, - i64sub: 1_300, - i32sub: 500, - i64mul: 2_000, - i32mul: 1_000, - i64divs: 3_500, - i32divs: 3_500, - - i64divu: 3_500, - i32divu: 3_500, - i64rems: 18_000, - i32rems: 15_000, - i64remu: 3_500, - i32remu: 3_500, - i64and: 1_000, - i32and: 500, - i64or: 1_000, - i32or: 500, - i64xor: 1_000, - i32xor: 500, - - i64shl: 1_000, - i32shl: 400, - i64shrs: 1_000, - i32shrs: 250, - i64shru: 1_000, - i32shru: 400, - i64rotl: 750, - i32rotl: 400, - i64rotr: 1_000, - i32rotr: 300, - }; - - let result = check_instructions_weights(weights, expected_weights); - - assert!(result.is_ok(), "{:#?}", result.err().unwrap()); - assert_eq!(result.unwrap(), expected_instructions_weights_count()); -} - -#[test] -fn syscall_weights_test() { - let weights = SyscallWeights::::default(); - - let expected = SyscallWeights { - alloc: 1_500_000.into(), - free: 900_000.into(), - free_range: 900_000.into(), - free_range_per_page: 40_000.into(), - gr_reserve_gas: 2_300_000.into(), - gr_unreserve_gas: 2_200_000.into(), - gr_system_reserve_gas: 1_200_000.into(), - gr_gas_available: 1_000_000.into(), - gr_message_id: 1_000_000.into(), - gr_program_id: 1_000_000.into(), - gr_source: 1_000_000.into(), - gr_value: 1_000_000.into(), - gr_value_available: 1_000_000.into(), - gr_size: 1_000_000.into(), - gr_read: 1_900_000.into(), - gr_read_per_byte: 200.into(), - gr_env_vars: 1_200_000.into(), - gr_block_height: 1_000_000.into(), - gr_block_timestamp: 1_000_000.into(), - gr_random: 1_900_000.into(), - gr_reply_deposit: 4_900_000.into(), - gr_send: 3_200_000.into(), - gr_send_per_byte: 500.into(), - gr_send_wgas: 3_300_000.into(), - gr_send_wgas_per_byte: 500.into(), - gr_send_init: 1_200_000.into(), - gr_send_push: 2_000_000.into(), - gr_send_push_per_byte: 500.into(), - gr_send_commit: 2_700_000.into(), - gr_send_commit_wgas: 2_700_000.into(), - gr_reservation_send: 3_400_000.into(), - gr_reservation_send_per_byte: 500.into(), - gr_reservation_send_commit: 2_900_000.into(), - gr_reply_commit: 12_000_000.into(), - gr_reply_commit_wgas: 12_000_000.into(), - gr_reservation_reply: 8_500_000.into(), - gr_reservation_reply_per_byte: 675_000.into(), - gr_reservation_reply_commit: 8_000_000.into(), - gr_reply_push: 1_700_000.into(), - gr_reply: 12_500_000.into(), - gr_reply_per_byte: 650.into(), - gr_reply_wgas: 12_500_000.into(), - gr_reply_wgas_per_byte: 650.into(), - gr_reply_push_per_byte: 640.into(), - gr_reply_to: 1_000_000.into(), - gr_signal_code: 1_000_000.into(), - gr_signal_from: 1_000_000.into(), - gr_reply_input: 20_000_000.into(), - gr_reply_input_wgas: 30_000_000.into(), - gr_reply_push_input: 1_200_000.into(), - gr_reply_push_input_per_byte: 110.into(), - gr_send_input: 3_100_000.into(), - gr_send_input_wgas: 3_100_000.into(), - gr_send_push_input: 1_500_000.into(), - gr_send_push_input_per_byte: 150.into(), - gr_debug: 1_200_000.into(), - gr_debug_per_byte: 500.into(), - gr_reply_code: 1_000_000.into(), - gr_exit: 18_000_000.into(), - gr_leave: 14_000_000.into(), - gr_wait: 14_000_000.into(), - gr_wait_for: 14_000_000.into(), - gr_wait_up_to: 14_500_000.into(), - gr_wake: 3_300_000.into(), - gr_create_program: 4_100_000.into(), - gr_create_program_payload_per_byte: 120.into(), - gr_create_program_salt_per_byte: 1_400.into(), - gr_create_program_wgas: 4_100_000.into(), - gr_create_program_wgas_payload_per_byte: 120.into(), - gr_create_program_wgas_salt_per_byte: 1_400.into(), - _phantom: Default::default(), - }; - - let result = check_syscall_weights(weights, expected); - - assert!(result.is_ok(), "{:#?}", result.err().unwrap()); - assert_eq!(result.unwrap(), expected_syscall_weights_count()); -} - -#[test] -fn page_costs_heuristic_test() { - let page_costs: LazyPagesCosts = MemoryWeights::::default().into(); - - let expected_page_costs = LazyPagesCosts { - load_page_data: 9_000_000.into(), - upload_page_data: 105_000_000.into(), - mem_grow: 800_000.into(), - mem_grow_per_page: 0.into(), - parachain_read_heuristic: 0.into(), - ..Default::default() - }; - - let result = check_pages_costs(page_costs, expected_page_costs); - - assert!(result.is_ok(), "{:#?}", result.err().unwrap()); - assert_eq!(result.unwrap(), expected_pages_costs_count()); -} - -#[test] -fn lazy_page_costs_heuristic_test() { - let lazy_pages_costs: LazyPagesCosts = MemoryWeights::::default().into(); - - let expected_lazy_pages_costs = LazyPagesCosts { - signal_read: 28_000_000.into(), - signal_write: 138_000_000.into(), - signal_write_after_read: 112_000_000.into(), - host_func_read: 29_000_000.into(), - host_func_write: 137_000_000.into(), - host_func_write_after_read: 112_000_000.into(), - load_page_storage_data: 9_000_000.into(), - ..Default::default() - }; - - let result = check_lazy_pages_costs(lazy_pages_costs, expected_lazy_pages_costs); - - assert!(result.is_ok(), "{:#?}", result.err().unwrap()); - assert_eq!(result.unwrap(), expected_lazy_pages_costs_count()); -} - -/// Check that it is not possible to write/change memory pages too cheaply, -/// because this may cause runtime heap memory overflow. -#[test] -fn write_is_not_too_cheap() { - let costs: LazyPagesCosts = MemoryWeights::::default().into(); - let cheapest_write = u64::MAX - .min(costs.signal_write.cost_for_one()) - .min(costs.signal_read.cost_for_one() + costs.signal_write_after_read.cost_for_one()) - .min(costs.host_func_write.cost_for_one()) - .min(costs.host_func_read.cost_for_one() + costs.host_func_write_after_read.cost_for_one()); - - let block_max_gas = 3 * 10 ^ 12; // 3 seconds - let runtime_heap_size_in_wasm_pages = 0x4000; // 1GB - assert!((block_max_gas / cheapest_write) < runtime_heap_size_in_wasm_pages); -} From 9771df9282b3e1c551767b5170fcceda1acc57e5 Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Wed, 13 Nov 2024 18:21:04 +0100 Subject: [PATCH 6/7] post-review fixes --- core/src/costs.rs | 34 ++++++++++++------ core/src/gas_metering/schedule.rs | 5 --- pallets/gear/src/schedule.rs | 25 +++++++++---- runtime/vara/src/tests/mod.rs | 31 ++++++++++------- runtime/vara/src/tests/utils.rs | 58 +++++++++++++------------------ 5 files changed, 86 insertions(+), 67 deletions(-) diff --git a/core/src/costs.rs b/core/src/costs.rs index 81f1e5cc1ec..1fcec7b2a97 100644 --- a/core/src/costs.rs +++ b/core/src/costs.rs @@ -502,6 +502,21 @@ impl SyscallCosts { } } +/// Memory pages costs. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct PagesCosts { + /// Loading from storage and moving it in program memory cost. + pub load_page_data: CostOf, + /// Uploading page data to storage cost. + pub upload_page_data: CostOf, + /// Memory grow cost. + pub mem_grow: CostOf, + /// Memory grow per page cost. + pub mem_grow_per_page: CostOf, + /// Parachain read heuristic cost. + pub parachain_read_heuristic: CostOf, +} + /// Memory pages lazy access costs. #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct LazyPagesCosts { @@ -519,16 +534,15 @@ pub struct LazyPagesCosts { pub host_func_write_after_read: CostOf, /// Loading page data from storage cost. pub load_page_storage_data: CostOf, - /// Loading from storage and moving it in program memory cost. - pub load_page_data: CostOf, - /// Uploading page data to storage cost. - pub upload_page_data: CostOf, - /// Memory grow cost. - pub mem_grow: CostOf, - /// Memory grow per page cost. - pub mem_grow_per_page: CostOf, - /// Parachain read heuristic cost. - pub parachain_read_heuristic: CostOf, +} + +/// IO costs. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct IoCosts { + /// Consts for common pages. + pub common: PagesCosts, + /// Consts for lazy pages. + pub lazy_pages: LazyPagesCosts, } /// Holding in storages rent costs. diff --git a/core/src/gas_metering/schedule.rs b/core/src/gas_metering/schedule.rs index 85e5a2fc12b..24b156a3b7b 100644 --- a/core/src/gas_metering/schedule.rs +++ b/core/src/gas_metering/schedule.rs @@ -1223,11 +1223,6 @@ impl From for LazyPagesCosts { .saturating_add(val.parachain_read_heuristic) .ref_time() .into(), - load_page_data: val.load_page_data.ref_time().into(), - upload_page_data: val.upload_page_data.ref_time().into(), - mem_grow: val.mem_grow.ref_time().into(), - mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), - parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), } } } diff --git a/pallets/gear/src/schedule.rs b/pallets/gear/src/schedule.rs index 093752f75ab..4ddaea1ad8d 100644 --- a/pallets/gear/src/schedule.rs +++ b/pallets/gear/src/schedule.rs @@ -24,7 +24,10 @@ use common::scheduler::SchedulingCostsPerBlock; use frame_support::{traits::Get, weights::Weight}; use gear_core::{ code::MAX_WASM_PAGES_AMOUNT, - costs::{ExtCosts, InstantiationCosts, LazyPagesCosts, ProcessCosts, RentCosts, SyscallCosts}, + costs::{ + ExtCosts, InstantiationCosts, IoCosts, LazyPagesCosts, PagesCosts, ProcessCosts, RentCosts, + SyscallCosts, + }, message, pages::{GearPage, WasmPage}, }; @@ -1301,6 +1304,21 @@ impl Default for MemoryWeights { } } +impl From> for IoCosts { + fn from(val: MemoryWeights) -> Self { + Self { + common: PagesCosts { + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), + }, + lazy_pages: LazyPagesCosts::from(val), + } + } +} + impl From> for LazyPagesCosts { fn from(val: MemoryWeights) -> Self { Self { @@ -1331,11 +1349,6 @@ impl From> for LazyPagesCosts { .saturating_add(val.parachain_read_heuristic) .ref_time() .into(), - load_page_data: val.load_page_data.ref_time().into(), - upload_page_data: val.upload_page_data.ref_time().into(), - mem_grow: val.mem_grow.ref_time().into(), - mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), - parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), } } } diff --git a/runtime/vara/src/tests/mod.rs b/runtime/vara/src/tests/mod.rs index 49d5b5dea86..d4eae04a6ec 100644 --- a/runtime/vara/src/tests/mod.rs +++ b/runtime/vara/src/tests/mod.rs @@ -23,7 +23,7 @@ use crate::Runtime; use frame_support::dispatch::GetDispatchInfo; use frame_system::limits::WeightsPerClass; -use gear_core::costs::LazyPagesCosts; +use gear_core::costs::{IoCosts, LazyPagesCosts, PagesCosts}; use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; use pallet_staking::WeightInfo as _; use sp_runtime::AccountId32; @@ -321,18 +321,17 @@ fn syscall_weights_test() { #[test] fn page_costs_heuristic_test() { - let page_costs: LazyPagesCosts = MemoryWeights::::default().into(); + let io_costs: IoCosts = MemoryWeights::::default().into(); - let expected_page_costs = LazyPagesCosts { + let expected_page_costs = PagesCosts { load_page_data: 9_000_000.into(), upload_page_data: 105_000_000.into(), mem_grow: 800_000.into(), mem_grow_per_page: 0.into(), parachain_read_heuristic: 0.into(), - ..Default::default() }; - let result = check_pages_costs(page_costs, expected_page_costs); + let result = check_pages_costs(io_costs.common, expected_page_costs); assert!(result.is_ok(), "{:#?}", result.err().unwrap()); assert_eq!(result.unwrap(), expected_pages_costs_count()); @@ -340,7 +339,7 @@ fn page_costs_heuristic_test() { #[test] fn lazy_page_costs_heuristic_test() { - let lazy_pages_costs: LazyPagesCosts = MemoryWeights::::default().into(); + let io_costs: IoCosts = MemoryWeights::::default().into(); let expected_lazy_pages_costs = LazyPagesCosts { signal_read: 28_000_000.into(), @@ -350,10 +349,9 @@ fn lazy_page_costs_heuristic_test() { host_func_write: 137_000_000.into(), host_func_write_after_read: 112_000_000.into(), load_page_storage_data: 9_000_000.into(), - ..Default::default() }; - let result = check_lazy_pages_costs(lazy_pages_costs, expected_lazy_pages_costs); + let result = check_lazy_pages_costs(io_costs.lazy_pages, expected_lazy_pages_costs); assert!(result.is_ok(), "{:#?}", result.err().unwrap()); assert_eq!(result.unwrap(), expected_lazy_pages_costs_count()); @@ -363,14 +361,21 @@ fn lazy_page_costs_heuristic_test() { /// because this may cause runtime heap memory overflow. #[test] fn write_is_not_too_cheap() { - let costs: LazyPagesCosts = MemoryWeights::::default().into(); + let costs: IoCosts = MemoryWeights::::default().into(); let cheapest_write = u64::MAX - .min(costs.signal_write.cost_for_one()) - .min(costs.signal_read.cost_for_one() + costs.signal_write_after_read.cost_for_one()) - .min(costs.host_func_write.cost_for_one()) - .min(costs.host_func_read.cost_for_one() + costs.host_func_write_after_read.cost_for_one()); + .min(costs.lazy_pages.signal_write.cost_for_one()) + .min( + costs.lazy_pages.signal_read.cost_for_one() + + costs.lazy_pages.signal_write_after_read.cost_for_one(), + ) + .min(costs.lazy_pages.host_func_write.cost_for_one()) + .min( + costs.lazy_pages.host_func_read.cost_for_one() + + costs.lazy_pages.host_func_write_after_read.cost_for_one(), + ); let block_max_gas = 3 * 10 ^ 12; // 3 seconds let runtime_heap_size_in_wasm_pages = 0x4000; // 1GB + assert!((block_max_gas / cheapest_write) < runtime_heap_size_in_wasm_pages); } diff --git a/runtime/vara/src/tests/utils.rs b/runtime/vara/src/tests/utils.rs index b30b776438e..c40a88e200f 100644 --- a/runtime/vara/src/tests/utils.rs +++ b/runtime/vara/src/tests/utils.rs @@ -19,7 +19,7 @@ use super::*; use crate::Runtime; -use gear_core::costs::LazyPagesCosts; +use gear_core::costs::{IoCosts, LazyPagesCosts, PagesCosts}; use pallet_gear::{InstructionWeights, MemoryWeights, SyscallWeights}; const INSTRUCTIONS_SPREAD: u8 = 50; @@ -252,21 +252,16 @@ pub(super) fn expected_syscall_weights_count() -> usize { } pub(super) fn expected_pages_costs_count() -> usize { - let LazyPagesCosts { - // Fields for lazy pages costs - signal_read: _, - signal_write: _, - signal_write_after_read: _, - host_func_read: _, - host_func_write: _, - host_func_write_after_read: _, - load_page_storage_data: _, - // Fields for pages costs - load_page_data: _, - upload_page_data: _, - mem_grow: _, - mem_grow_per_page: _, - parachain_read_heuristic: _, + let IoCosts { + lazy_pages: _, + common: + PagesCosts { + load_page_data: _, + upload_page_data: _, + mem_grow: _, + mem_grow_per_page: _, + parachain_read_heuristic: _, + }, } = MemoryWeights::::default().into(); // total number of lazy pages costs @@ -274,21 +269,18 @@ pub(super) fn expected_pages_costs_count() -> usize { } pub(super) fn expected_lazy_pages_costs_count() -> usize { - let LazyPagesCosts { - // Fields for lazy pages costs - signal_read: _, - signal_write: _, - signal_write_after_read: _, - host_func_read: _, - host_func_write: _, - host_func_write_after_read: _, - load_page_storage_data: _, - // Fields for pages costs - load_page_data: _, - upload_page_data: _, - mem_grow: _, - mem_grow_per_page: _, - parachain_read_heuristic: _, + let IoCosts { + common: _, + lazy_pages: + LazyPagesCosts { + signal_read: _, + signal_write: _, + signal_write_after_read: _, + host_func_read: _, + host_func_write: _, + host_func_write_after_read: _, + load_page_storage_data: _, + }, } = MemoryWeights::::default().into(); // total number of lazy pages costs @@ -527,8 +519,8 @@ pub(super) fn check_lazy_pages_costs( /// Check that the pages costs are within the expected range pub(super) fn check_pages_costs( - page_costs: LazyPagesCosts, - expected_page_costs: LazyPagesCosts, + page_costs: PagesCosts, + expected_page_costs: PagesCosts, ) -> Result> { macro_rules! expectation { ($inst_name:ident) => { From b82d24a483b0656798579a9b2606a7c1dae07b58 Mon Sep 17 00:00:00 2001 From: Andrey Lazarko Date: Tue, 26 Nov 2024 11:46:07 +0100 Subject: [PATCH 7/7] post-review fixes --- core/src/gas_metering/schedule.rs | 21 +++++++++++++++++++++ pallets/gear/src/schedule.rs | 20 +++++++++++++------- utils/weight-diff/src/main.rs | 2 ++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/core/src/gas_metering/schedule.rs b/core/src/gas_metering/schedule.rs index 24b156a3b7b..7053e318531 100644 --- a/core/src/gas_metering/schedule.rs +++ b/core/src/gas_metering/schedule.rs @@ -1193,6 +1193,27 @@ impl From for SyscallCosts { } } +impl From for IoCosts { + fn from(val: MemoryWeights) -> Self { + Self { + common: PagesCosts::from(val.clone()), + lazy_pages: LazyPagesCosts::from(val), + } + } +} + +impl From for PagesCosts { + fn from(val: MemoryWeights) -> Self { + Self { + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), + } + } +} + impl From for LazyPagesCosts { fn from(val: MemoryWeights) -> Self { Self { diff --git a/pallets/gear/src/schedule.rs b/pallets/gear/src/schedule.rs index 4ddaea1ad8d..e08bf851a88 100644 --- a/pallets/gear/src/schedule.rs +++ b/pallets/gear/src/schedule.rs @@ -1307,18 +1307,24 @@ impl Default for MemoryWeights { impl From> for IoCosts { fn from(val: MemoryWeights) -> Self { Self { - common: PagesCosts { - load_page_data: val.load_page_data.ref_time().into(), - upload_page_data: val.upload_page_data.ref_time().into(), - mem_grow: val.mem_grow.ref_time().into(), - mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), - parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), - }, + common: PagesCosts::from(val.clone()), lazy_pages: LazyPagesCosts::from(val), } } } +impl From> for PagesCosts { + fn from(val: MemoryWeights) -> Self { + Self { + load_page_data: val.load_page_data.ref_time().into(), + upload_page_data: val.upload_page_data.ref_time().into(), + mem_grow: val.mem_grow.ref_time().into(), + mem_grow_per_page: val.mem_grow_per_page.ref_time().into(), + parachain_read_heuristic: val.parachain_read_heuristic.ref_time().into(), + } + } +} + impl From> for LazyPagesCosts { fn from(val: MemoryWeights) -> Self { Self { diff --git a/utils/weight-diff/src/main.rs b/utils/weight-diff/src/main.rs index 51f4056d94d..684e01a3104 100644 --- a/utils/weight-diff/src/main.rs +++ b/utils/weight-diff/src/main.rs @@ -308,6 +308,8 @@ const TYPE_LIST: &[&str] = &[ "MemoryCosts", "RentCosts", "InstantiationCosts", + "IoCosts", + "PagesCosts", "LazyPagesCosts", ];