diff --git a/radix-engine-tests/assets/blueprints/transaction_limits/src/transaction_limits.rs b/radix-engine-tests/assets/blueprints/transaction_limits/src/transaction_limits.rs index 91fac94f386..578b2d761f9 100644 --- a/radix-engine-tests/assets/blueprints/transaction_limits/src/transaction_limits.rs +++ b/radix-engine-tests/assets/blueprints/transaction_limits/src/transaction_limits.rs @@ -1,4 +1,3 @@ -use sbor::*; use scrypto::prelude::*; #[derive(Sbor, ScryptoEvent)] @@ -92,32 +91,38 @@ mod transaction_limits_substate { } impl TransactionLimitSubstateTest { - pub fn write_large_value(raw_array_size: usize) -> Global { - // SBOR encoding of Vec - let mut buf = Vec::new(); - let mut encoder = VecEncoder::::new(&mut buf, 100); - encoder - .write_payload_prefix(SCRYPTO_SBOR_V1_PAYLOAD_PREFIX) - .unwrap(); - encoder.write_value_kind(ValueKind::Array).unwrap(); - encoder.write_value_kind(ValueKind::U8).unwrap(); - encoder.write_size(raw_array_size).unwrap(); - buf.reserve(raw_array_size); - let new_len = buf.len() + raw_array_size; - unsafe { buf.set_len(new_len) }; - + pub fn write_large_values( + raw_array_sizes: Vec, + ) -> Global { // Create a KVStore let kv_store = KeyValueStore::>::new(); - - // Insert into store - let key_payload = scrypto_encode(&1u32).unwrap(); - let handle = ScryptoVmV1Api::kv_store_open_entry( - kv_store.id.as_node_id(), - &key_payload, - LockFlags::MUTABLE, - ); - unsafe { wasm_api::kv_entry::kv_entry_write(handle, buf.as_ptr(), buf.len()) }; - ScryptoVmV1Api::kv_entry_close(handle); + let mut key_value = 0u32; + for raw_array_size in raw_array_sizes { + // SBOR encoding of Vec + let mut buf = Vec::new(); + let mut encoder = VecEncoder::::new(&mut buf, 100); + encoder + .write_payload_prefix(SCRYPTO_SBOR_V1_PAYLOAD_PREFIX) + .unwrap(); + encoder.write_value_kind(ValueKind::Array).unwrap(); + encoder.write_value_kind(ValueKind::U8).unwrap(); + encoder.write_size(raw_array_size).unwrap(); + buf.reserve(raw_array_size); + let new_len = buf.len() + raw_array_size; + unsafe { buf.set_len(new_len) }; + + // Insert into store + let key_payload = scrypto_encode(&key_value).unwrap(); + let handle = ScryptoVmV1Api::kv_store_open_entry( + kv_store.id.as_node_id(), + &key_payload, + LockFlags::MUTABLE, + ); + unsafe { wasm_api::kv_entry::kv_entry_write(handle, buf.as_ptr(), buf.len()) }; + ScryptoVmV1Api::kv_entry_close(handle); + + key_value += 1; + } // Put the kv store into a component TransactionLimitSubstateTest { kv_store } @@ -125,6 +130,19 @@ mod transaction_limits_substate { .prepare_to_globalize(OwnerRole::None) .globalize() } + + pub fn read_values(&self, limit: u32) { + for key in 0..limit { + let key_payload = scrypto_encode(&key).unwrap(); + let handle = ScryptoVmV1Api::kv_store_open_entry( + self.kv_store.id.as_node_id(), + &key_payload, + LockFlags::read_only(), + ); + let _raw_bytes = ScryptoVmV1Api::kv_entry_read(handle); + ScryptoVmV1Api::kv_entry_close(handle); + } + } } } diff --git a/radix-engine-tests/benches/costing.rs b/radix-engine-tests/benches/costing.rs index f91273995d0..9f9dc005008 100644 --- a/radix-engine-tests/benches/costing.rs +++ b/radix-engine-tests/benches/costing.rs @@ -23,26 +23,101 @@ use sbor::rust::iter; use scrypto_test::prelude::LedgerSimulatorBuilder; use wabt::wat2wasm; -fn bench_decode_sbor(c: &mut Criterion) { +fn generate_interesting_bytes_of_length(length: usize) -> Vec { + include_workspace_asset_bytes!("radix-transaction-scenarios", "radiswap.rpd") + .iter() + .cycle() + .take(length) + .cloned() + .collect() +} + +fn bench_decode_rpd_to_manifest_value(c: &mut Criterion) { let payload = include_workspace_asset_bytes!("radix-transaction-scenarios", "radiswap.rpd"); println!("Payload size: {}", payload.len()); - c.bench_function("costing::decode_sbor", |b| { + c.bench_function("costing::decode_rpd_to_manifest_value", |b| { b.iter(|| manifest_decode::(payload)) }); } -fn bench_decode_sbor_bytes(c: &mut Criterion) { - let payload = manifest_encode(include_workspace_asset_bytes!( - "radix-transaction-scenarios", - "radiswap.rpd" - )) - .unwrap(); +fn bench_decode_rpd_to_manifest_raw_value(c: &mut Criterion) { + let payload = include_workspace_asset_bytes!("radix-transaction-scenarios", "radiswap.rpd"); println!("Payload size: {}", payload.len()); - c.bench_function("costing::decode_sbor_bytes", |b| { + c.bench_function("costing::decode_rpd_to_manifest_raw_value", |b| { + b.iter(|| manifest_decode::(payload)) + }); +} + +fn bench_decode_encoded_u8_array_to_manifest_value(c: &mut Criterion) { + let example_bytes = generate_interesting_bytes_of_length(1000000); + let payload = manifest_encode(&example_bytes).unwrap(); + println!("Payload size: {}", payload.len()); + c.bench_function("costing::decode_encoded_u8_array_to_manifest_value", |b| { b.iter(|| manifest_decode::(&payload)) }); } +fn bench_decode_encoded_u8_array_to_manifest_raw_value(c: &mut Criterion) { + let example_bytes = generate_interesting_bytes_of_length(1000000); + let payload = manifest_encode(&example_bytes).unwrap(); + println!("Payload size: {}", payload.len()); + c.bench_function( + "costing::decode_encoded_u8_array_to_manifest_raw_value", + |b| b.iter(|| manifest_decode::(&payload)), + ); +} + +fn bench_decode_encoded_i8_array_to_manifest_value(c: &mut Criterion) { + let example_i8_array = generate_interesting_bytes_of_length(1000000) + .into_iter() + .map(|b| i8::from_be_bytes([b])) + .collect::>(); + let payload = manifest_encode(&example_i8_array).unwrap(); + println!("Payload size: {}", payload.len()); + c.bench_function("costing::decode_encoded_i8_array_to_manifest_value", |b| { + b.iter(|| manifest_decode::(&payload)) + }); +} + +fn bench_decode_encoded_i8_array_to_manifest_raw_value(c: &mut Criterion) { + let example_i8_array = generate_interesting_bytes_of_length(1000000) + .into_iter() + .map(|b| i8::from_be_bytes([b])) + .collect::>(); + let payload = manifest_encode(&example_i8_array).unwrap(); + println!("Payload size: {}", payload.len()); + c.bench_function( + "costing::decode_encoded_i8_array_to_manifest_raw_value", + |b| b.iter(|| manifest_decode::(&payload)), + ); +} + +fn bench_decode_encoded_tuple_array_to_manifest_value(c: &mut Criterion) { + let value = generate_interesting_bytes_of_length(1000000) + .into_iter() + .map(|b| (b,)) + .collect::>(); + let payload = manifest_encode(&value).unwrap(); + println!("Payload size: {}", payload.len()); + c.bench_function( + "costing::decode_encoded_tuple_array_to_manifest_value", + |b| b.iter(|| manifest_decode::(&payload)), + ); +} + +fn bench_decode_encoded_tuple_array_to_manifest_raw_value(c: &mut Criterion) { + let value = generate_interesting_bytes_of_length(1000000) + .into_iter() + .map(|b| (b,)) + .collect::>(); + let payload = manifest_encode(&value).unwrap(); + println!("Payload size: {}", payload.len()); + c.bench_function( + "costing::decode_encoded_tuple_array_to_manifest_raw_value", + |b| b.iter(|| manifest_decode::(&payload)), + ); +} + fn bench_validate_sbor_payload(c: &mut Criterion) { let package_definition = manifest_decode::(include_workspace_asset_bytes!( "radix-transaction-scenarios", @@ -228,10 +303,92 @@ fn bench_prepare_wasm(c: &mut Criterion) { }); } +fn bench_execute_transaction_creating_big_vec_substates(c: &mut Criterion) { + let mut ledger = LedgerSimulatorBuilder::new().without_kernel_trace().build(); + + let (code, definition) = PackageLoader::get("transaction_limits"); + let package_address = + ledger.publish_package((code, definition), BTreeMap::new(), OwnerRole::None); + + let substate_sizes = [ + 1000, + 100000, + MAX_SUBSTATE_VALUE_SIZE - 100, + MAX_SUBSTATE_VALUE_SIZE - 100, + MAX_SUBSTATE_VALUE_SIZE - 100, + MAX_SUBSTATE_VALUE_SIZE - 100, + ]; + + c.bench_function( + "costing::execute_transaction_creating_big_vec_substates", + |b| { + b.iter(|| { + ledger + .call_function( + package_address, + "TransactionLimitSubstateTest", + "write_large_values", + manifest_args!(&substate_sizes), + ) + .expect_commit_success(); + }) + }, + ); +} + +fn bench_execute_transaction_reading_big_vec_substates(c: &mut Criterion) { + let mut ledger = LedgerSimulatorBuilder::new().without_kernel_trace().build(); + + let (code, definition) = PackageLoader::get("transaction_limits"); + let package_address = + ledger.publish_package((code, definition), BTreeMap::new(), OwnerRole::None); + + let substate_sizes = [ + 1000, + 100000, + MAX_SUBSTATE_VALUE_SIZE - 100, + MAX_SUBSTATE_VALUE_SIZE - 100, + MAX_SUBSTATE_VALUE_SIZE - 100, + MAX_SUBSTATE_VALUE_SIZE - 100, + ]; + let component_address = ledger + .call_function( + package_address, + "TransactionLimitSubstateTest", + "write_large_values", + manifest_args!(&substate_sizes), + ) + .expect_commit_success() + .new_component_addresses()[0]; + + let substates_to_read = substate_sizes.len() as u32; + + c.bench_function( + "costing::execute_transaction_reading_big_vec_substates", + |b| { + b.iter(|| { + ledger + .call_method( + component_address, + "read_values", + manifest_args!(substates_to_read), + ) + .expect_commit_success(); + }) + }, + ); +} + criterion_group!( costing, - bench_decode_sbor, - bench_decode_sbor_bytes, + bench_decode_rpd_to_manifest_value, + bench_decode_rpd_to_manifest_raw_value, + bench_decode_encoded_u8_array_to_manifest_value, + bench_decode_encoded_u8_array_to_manifest_raw_value, + bench_decode_encoded_i8_array_to_manifest_value, + bench_decode_encoded_i8_array_to_manifest_raw_value, + bench_decode_encoded_tuple_array_to_manifest_value, + bench_decode_encoded_tuple_array_to_manifest_raw_value, bench_validate_sbor_payload, bench_validate_sbor_payload_bytes, bench_validate_secp256k1, @@ -241,5 +398,7 @@ criterion_group!( bench_deserialize_wasm, bench_validate_wasm, bench_prepare_wasm, + bench_execute_transaction_creating_big_vec_substates, + bench_execute_transaction_reading_big_vec_substates, ); criterion_main!(costing); diff --git a/radix-engine-tests/tests/system/transaction_limits.rs b/radix-engine-tests/tests/system/transaction_limits.rs index c14833d0846..90b15bd0f45 100644 --- a/radix-engine-tests/tests/system/transaction_limits.rs +++ b/radix-engine-tests/tests/system/transaction_limits.rs @@ -206,8 +206,8 @@ fn test_default_substate_size_limit() { .call_function( package_address, "TransactionLimitSubstateTest", - "write_large_value", - manifest_args!(MAX_SUBSTATE_VALUE_SIZE - 17), + "write_large_values", + manifest_args!([MAX_SUBSTATE_VALUE_SIZE - 17]), ) .build(); let receipt = ledger.execute_manifest(manifest, vec![]); @@ -221,8 +221,8 @@ fn test_default_substate_size_limit() { .call_function( package_address, "TransactionLimitSubstateTest", - "write_large_value", - manifest_args!(MAX_SUBSTATE_VALUE_SIZE - 16), + "write_large_values", + manifest_args!([MAX_SUBSTATE_VALUE_SIZE - 16]), ) .build(); let receipt = ledger.execute_manifest(manifest, vec![]);