From ab2bd8c26275fc00cb53f425b39fa3beeabcaa17 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Tue, 5 Nov 2024 18:34:09 +0000 Subject: [PATCH] [executor-benchmark] Simple script loading benchmark (#15098) --- crates/transaction-generator-lib/src/args.rs | 2 ++ .../src/publishing/module_simple.rs | 19 +++++++++++--- .../src/publishing/publish_util.rs | 25 +++++++++++++++++-- .../src/publishing/raw_module_data.rs | 10 ++++++++ .../src/packages/simple/scripts/main.move | 17 +++++++++++++ testsuite/single_node_performance.py | 2 ++ 6 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 testsuite/module-publish/src/packages/simple/scripts/main.move diff --git a/crates/transaction-generator-lib/src/args.rs b/crates/transaction-generator-lib/src/args.rs index 29bcf6dce82df..b19bf2651e8b4 100644 --- a/crates/transaction-generator-lib/src/args.rs +++ b/crates/transaction-generator-lib/src/args.rs @@ -72,6 +72,7 @@ pub enum TransactionTypeArg { SmartTablePicture1BWith256Change, SmartTablePicture1MWith1KChangeExceedsLimit, DeserializeU256, + SimpleScript, } impl TransactionTypeArg { @@ -318,6 +319,7 @@ impl TransactionTypeArg { }) }, TransactionTypeArg::DeserializeU256 => call_custom_module(EntryPoints::DeserializeU256), + TransactionTypeArg::SimpleScript => call_custom_module(EntryPoints::SimpleScript), } } diff --git a/crates/transaction-generator-lib/src/publishing/module_simple.rs b/crates/transaction-generator-lib/src/publishing/module_simple.rs index 3f2e234d220d1..0bc7b959fb408 100644 --- a/crates/transaction-generator-lib/src/publishing/module_simple.rs +++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 #![allow(unused)] +use crate::publishing::publish_util::Package; use aptos_framework::natives::code::{MoveOption, PackageMetadata}; use aptos_sdk::{ bcs, @@ -11,7 +12,7 @@ use aptos_sdk::{ }, types::{ serde_helper::bcs_utils::bcs_size_of_byte_array, - transaction::{EntryFunction, TransactionPayload}, + transaction::{EntryFunction, Script, TransactionPayload}, }, }; use move_binary_format::{ @@ -267,6 +268,10 @@ pub enum EntryPoints { num_points_per_txn: usize, }, DeserializeU256, + /// No-op script with dependencies in *::simple.move. The script has unreachable code that is + /// there to slow down deserialization & verification, effectively making it more expensive to + /// load it into code cache. + SimpleScript, } impl EntryPoints { @@ -291,7 +296,8 @@ impl EntryPoints { | EntryPoints::BytesMakeOrChange { .. } | EntryPoints::EmitEvents { .. } | EntryPoints::MakeOrChangeTable { .. } - | EntryPoints::MakeOrChangeTableRandom { .. } => "simple", + | EntryPoints::MakeOrChangeTableRandom { .. } + | EntryPoints::SimpleScript => "simple", EntryPoints::IncGlobal | EntryPoints::IncGlobalAggV2 | EntryPoints::ModifyGlobalBoundedAggV2 { .. } @@ -347,7 +353,8 @@ impl EntryPoints { | EntryPoints::BytesMakeOrChange { .. } | EntryPoints::EmitEvents { .. } | EntryPoints::MakeOrChangeTable { .. } - | EntryPoints::MakeOrChangeTableRandom { .. } => "simple", + | EntryPoints::MakeOrChangeTableRandom { .. } + | EntryPoints::SimpleScript => "simple", EntryPoints::IncGlobal | EntryPoints::IncGlobalAggV2 | EntryPoints::ModifyGlobalBoundedAggV2 { .. } => "aggregator_example", @@ -411,6 +418,9 @@ impl EntryPoints { }, EntryPoints::Double => get_payload_void(module_id, ident_str!("double").to_owned()), EntryPoints::Half => get_payload_void(module_id, ident_str!("half").to_owned()), + EntryPoints::SimpleScript => { + Package::script(*other.expect("Must provide sender's address")) + }, // 1 arg EntryPoints::Loop { loop_count, @@ -791,7 +801,8 @@ impl EntryPoints { | EntryPoints::BytesMakeOrChange { .. } | EntryPoints::EmitEvents { .. } | EntryPoints::MakeOrChangeTable { .. } - | EntryPoints::MakeOrChangeTableRandom { .. } => AutomaticArgs::Signer, + | EntryPoints::MakeOrChangeTableRandom { .. } + | EntryPoints::SimpleScript => AutomaticArgs::Signer, EntryPoints::Nop2Signers | EntryPoints::Nop5Signers => AutomaticArgs::SignerAndMultiSig, EntryPoints::IncGlobal | EntryPoints::IncGlobalAggV2 diff --git a/crates/transaction-generator-lib/src/publishing/publish_util.rs b/crates/transaction-generator-lib/src/publishing/publish_util.rs index 75b2bf7ee3a46..68924e485ada2 100644 --- a/crates/transaction-generator-lib/src/publishing/publish_util.rs +++ b/crates/transaction-generator-lib/src/publishing/publish_util.rs @@ -11,11 +11,15 @@ use aptos_sdk::{ transaction_builder::{aptos_stdlib, TransactionFactory}, types::{ account_address::AccountAddress, - transaction::{SignedTransaction, TransactionPayload}, + transaction::{Script, SignedTransaction, TransactionPayload}, LocalAccount, }, }; -use move_binary_format::{access::ModuleAccess, file_format::SignatureToken, CompiledModule}; +use move_binary_format::{ + access::ModuleAccess, + file_format::{CompiledScript, SignatureToken}, + CompiledModule, +}; use rand::{rngs::StdRng, Rng}; // Information used to track a publisher and what allows to identify and @@ -127,6 +131,23 @@ impl Package { Self::Simple(modules, metadata) } + pub fn script(publisher: AccountAddress) -> TransactionPayload { + let code = &*raw_module_data::SCRIPT_SIMPLE; + let mut script = CompiledScript::deserialize(code).expect("Script must deserialize"); + + // Change the constant to the sender's address to change script's hash. + for constant in &mut script.constant_pool { + if constant.type_ == SignatureToken::Address { + constant.data = bcs::to_bytes(&publisher).expect("Address must serialize"); + break; + } + } + + let mut code = vec![]; + script.serialize(&mut code).expect("Script must serialize"); + TransactionPayload::Script(Script::new(code, vec![], vec![])) + } + fn load_package( package_bytes: &[u8], modules_bytes: &[Vec], diff --git a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs index 66e6fe439a825..4deb1a72d1709 100644 --- a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs +++ b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs @@ -762,6 +762,16 @@ pub static PACKAGE_SIMPLE_METADATA: Lazy> = Lazy::new(|| { ] }); +#[rustfmt::skip] +pub static SCRIPT_SIMPLE: Lazy> = Lazy::new(|| { + vec![ + 161, 28, 235, 11, 7, 0, 0, 10, 2, 5, 0, 4, 6, 4, 34, 1, 6, 12, + 0, 5, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 3, 11, 0, 1, 2, + ] +}); + #[rustfmt::skip] pub static MODULE_SIMPLE_SIMPLE: Lazy> = Lazy::new(|| { vec![ diff --git a/testsuite/module-publish/src/packages/simple/scripts/main.move b/testsuite/module-publish/src/packages/simple/scripts/main.move new file mode 100644 index 0000000000000..0c6c4767afb65 --- /dev/null +++ b/testsuite/module-publish/src/packages/simple/scripts/main.move @@ -0,0 +1,17 @@ +script { + // Note: this constant can be replaced in compiled script to make it hash to a different value. + const SENDER: address = @0x1; + + fun main(sender: &signer) { + // The idea is to to ensure that this script takes some time to be deserialized and verified, but the actual + // execution time is small (no-op). + if (false) { + 0xABCD::simple::loop_nop(sender, 0); + 0xABCD::simple::loop_arithmetic(sender, 0); + 0xABCD::simple::loop_bcs(sender, 0, 0); + if (false) { + while (true) {} + } + } + } +} diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 7ca1aea5ce604..cd98a98953ca9 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -293,6 +293,8 @@ class RunGroupConfig: RunGroupConfig(expected_tps=6800, key=RunGroupKey("token-v2-ambassador-mint"), included_in=Flow.MAINNET_LARGE_DB), # RunGroupConfig(expected_tps=17000 if NUM_ACCOUNTS < 5000000 else 28000, key=RunGroupKey("coin_transfer_connected_components", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--connected-tx-grps 5000", transaction_type_override=""), included_in=Flow.MAINNET | Flow.MAINNET_LARGE_DB, waived=True), # RunGroupConfig(expected_tps=27000 if NUM_ACCOUNTS < 5000000 else 23000, key=RunGroupKey("coin_transfer_hotspot", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--hotspot-probability 0.8", transaction_type_override=""), included_in=Flow.MAINNET | Flow.MAINNET_LARGE_DB, waived=True), + + RunGroupConfig(expected_tps=1000, key=RunGroupKey("simple-script"), included_in=LAND_BLOCKING_AND_C, waived=True), ] # fmt: on