Skip to content

Commit

Permalink
feat: new approach for benchmarking execute scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
neutrinoks committed May 23, 2024
1 parent 6a12b2c commit ac61010
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 182 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ gas_costs.txt

# Move Build Output
build/

Calibration.move
gen_smove_instr.sh
2 changes: 1 addition & 1 deletion doc/tech_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl pallet_move::Config for Test {
// Runtime event of this blockchain.
type RuntimeEvent = RuntimeEvent;
// Weight info for this pallet.
type WeightInfo = (); // or use pallet_move::weights::SubstrateWeights<Test>;
type WeightInfo = pallet_move::weights::SubstrateWeight<Test>;
}
```

Expand Down
2 changes: 2 additions & 0 deletions pallet/src/assets/move-projects/gas-costs/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh
cd $(dirname $0)
ALICE=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
sh ./gen_cal_scripts.sh
# Build the project
smove build
# Create all Script-Transactions
Expand All @@ -10,3 +11,4 @@ smove create-transaction --compiled-script-path build/gas-costs/bytecode_scripts
mv build/gas-costs/script_transactions/long_script.mvt build/gas-costs/script_transactions/long_cheap_script.mvt
smove create-transaction --compiled-script-path build/gas-costs/bytecode_scripts/long_script.mv --args signer:$ALICE bool:false
mv build/gas-costs/script_transactions/long_script.mvt build/gas-costs/script_transactions/long_expensive_script.mvt
sh ./gen_smove_instr.sh
41 changes: 41 additions & 0 deletions pallet/src/assets/move-projects/gas-costs/gen_cal_scripts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/sh
cd $(dirname $0)

MOVE_SRC="./sources/Calibration.move"
BASH_SH="./gen_smove_instr.sh"
ITERATIONS=25

function write_method() {
printf "script {\n" >> $MOVE_SRC
printf " fun cal_gas_cost_$1(v0: u8" >> $MOVE_SRC
if [ $1 -gt 0 ]
then
for i in $(seq 1 $1)
do
printf ", v$i: u8" >> $MOVE_SRC
done
fi
printf ") {\n" >> $MOVE_SRC
for i in $(seq 0 $1)
do
printf " assert!(v$i == $i, $i);\n" >> $MOVE_SRC
done
printf " }\n" >> $MOVE_SRC
printf "}\n" >> $MOVE_SRC
}

function write_smove_cmd() {
printf "\nsmove create-transaction -c build/gas-costs/bytecode_scripts/cal_gas_cost_$1.mv --args" >> $BASH_SH
for i in $(seq 0 $1)
do
printf " u8:$i" >> $BASH_SH
done
}

printf "" > $MOVE_SRC
printf "#!/bin/sh" > $BASH_SH
for i in $(seq 0 $(($ITERATIONS-1)))
do
write_method $i
write_smove_cmd $i
done
220 changes: 71 additions & 149 deletions pallet/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,144 +2,76 @@
use frame_benchmarking::v2::*;
use frame_system::{Config as SysConfig, RawOrigin};
use pallet_balances::{Config as BalancesConfig, Pallet as Balances};
use sp_core::crypto::Ss58Codec;

use crate::{mock_utils as utils, *};

const LIMIT: u128 = 60_000_000_000_000;

const MAX_GAS_AMOUNT: u32 = u32::MAX;

type SourceOf<T> = <<T as SysConfig>::Lookup as sp_runtime::traits::StaticLookup>::Source;

macro_rules! impl_gas_costs_cal_fns {
($name:tt) => {
pub fn $name() -> &'static [u8] {
core::include_bytes!(concat!(
"assets/move-projects/gas-costs/build/gas-costs/script_transactions/",
stringify!($name),
".mvt"
))
}
};
}

#[benchmarks(
where
T: Config + SysConfig + BalancesConfig,
T: Config + SysConfig,
T::AccountId: Ss58Codec,
T::Balance: From<u128>,
SourceOf<T>: From<T::AccountId>,
)]
mod benchmarks {
use super::*;

/// Because it is challenging to determine a reliable and fixed relation between gas costs and
/// Substrate weights, we created Move scripts with known gas costs and increasing steps of 20.
/// Twenty-five scripts with rising gas costs of about 20 for each iteration step were used as
/// input for this benchmark. Therefore, the original output was divided by 20 afterwards.
#[benchmark]
fn execute(n: Linear<0, 7>) {
let bob_32 = utils::account::<T>(utils::BOB_ADDR);
fn execute(n: Linear<0, 24>) {
let alice_32 = utils::account::<T>(utils::ALICE_ADDR);
let dave_32 = utils::account::<T>(utils::DAVE_ADDR);
let eve_32 = utils::account::<T>(utils::EVE_ADDR);

// Our benchmark plan (each is a test scenario with different parameters).
let script_bcs = [
car_wash_initial_coin_miniting().to_vec(),
car_wash_register_new_user().to_vec(),
car_wash_buy_coin().to_vec(),
car_wash_wash_car().to_vec(),
gas_costs_short_cheap_script().to_vec(),
gas_costs_long_cheap_script().to_vec(),
multiple_signers_init_module().to_vec(),
multiple_signers_rent_apartment().to_vec(),
];
// Sequence of account-IDs who will execute each extrinsic call.
let accounts = [
bob_32.clone(), // car-wash-example
alice_32.clone(),
alice_32.clone(),
alice_32.clone(),
alice_32.clone(), // gas-costs
alice_32.clone(),
bob_32.clone(), // multiple-signers
eve_32,
cal_gas_cost_0().to_vec(),
cal_gas_cost_1().to_vec(),
cal_gas_cost_2().to_vec(),
cal_gas_cost_3().to_vec(),
cal_gas_cost_4().to_vec(),
cal_gas_cost_5().to_vec(),
cal_gas_cost_6().to_vec(),
cal_gas_cost_7().to_vec(),
cal_gas_cost_8().to_vec(),
cal_gas_cost_9().to_vec(),
cal_gas_cost_10().to_vec(),
cal_gas_cost_11().to_vec(),
cal_gas_cost_12().to_vec(),
cal_gas_cost_13().to_vec(),
cal_gas_cost_14().to_vec(),
cal_gas_cost_15().to_vec(),
cal_gas_cost_16().to_vec(),
cal_gas_cost_17().to_vec(),
cal_gas_cost_18().to_vec(),
cal_gas_cost_19().to_vec(),
cal_gas_cost_20().to_vec(),
cal_gas_cost_21().to_vec(),
cal_gas_cost_22().to_vec(),
cal_gas_cost_23().to_vec(),
cal_gas_cost_24().to_vec(),
];
// Needed gas amounts for each script, estimated by smove.
let gas = [343, 197, 795, 425, 1, 8, 308, 1377];
// Balance limit to be used.
let regular = [LIMIT; 2];
let max = [u128::MAX; 2];
let limit = [regular, regular, max, regular].concat();

// Now we have to prepare each script execution with a proper setup.
// Publish both modules always.
Pallet::<T>::publish_module(
RawOrigin::Signed(bob_32.clone()).into(),
car_wash_example_module().to_vec(),
MAX_GAS_AMOUNT,
)
.unwrap();
Pallet::<T>::publish_module(
RawOrigin::Signed(bob_32.clone()).into(),
multiple_signers_module().to_vec(),
MAX_GAS_AMOUNT,
)
.unwrap();

// Now prepare individual situations for proper script sequences.
if n > 0 && n < 6 {
Pallet::<T>::execute(
RawOrigin::Signed(bob_32.clone()).into(),
car_wash_initial_coin_miniting().to_vec(),
MAX_GAS_AMOUNT,
LIMIT.into(),
)
.unwrap();
if n > 1 {
Pallet::<T>::execute(
RawOrigin::Signed(alice_32.clone()).into(),
car_wash_register_new_user().to_vec(),
MAX_GAS_AMOUNT,
LIMIT.into(),
)
.unwrap();
}
if n > 2 && n < 4 {
Pallet::<T>::execute(
RawOrigin::Signed(alice_32.clone()).into(),
car_wash_buy_coin().to_vec(),
MAX_GAS_AMOUNT,
LIMIT.into(),
)
.unwrap();
}
if n > 3 {
Balances::<T>::force_set_balance(
RawOrigin::Root.into(),
alice_32.clone().into(),
u128::MAX.into(),
)
.unwrap();
}
}
if n > 6 {
Pallet::<T>::execute(
RawOrigin::Signed(bob_32.clone()).into(),
multiple_signers_init_module().to_vec(),
MAX_GAS_AMOUNT,
LIMIT.into(),
)
.unwrap();
Pallet::<T>::execute(
RawOrigin::Signed(alice_32.clone()).into(),
multiple_signers_rent_apartment().to_vec(),
MAX_GAS_AMOUNT,
LIMIT.into(),
)
.unwrap();
Pallet::<T>::execute(
RawOrigin::Signed(dave_32).into(),
multiple_signers_rent_apartment().to_vec(),
MAX_GAS_AMOUNT,
LIMIT.into(),
)
.unwrap();
}

#[extrinsic_call]
execute(
RawOrigin::Signed(accounts[n as usize].clone()),
RawOrigin::Signed(alice_32),
script_bcs[n as usize].clone(),
gas[n as usize],
limit[n as usize].into(),
(n + 1) * 20,
0u128.into(),
)
}

Expand Down Expand Up @@ -243,26 +175,6 @@ mod benchmark_only {
)
}

pub fn car_wash_initial_coin_miniting() -> &'static [u8] {
core::include_bytes!("assets/move-projects/car-wash-example/build/car-wash-example/script_transactions/initial_coin_minting.mvt")
}

pub fn car_wash_register_new_user() -> &'static [u8] {
core::include_bytes!("assets/move-projects/car-wash-example/build/car-wash-example/script_transactions/register_new_user.mvt")
}

pub fn car_wash_buy_coin() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/car-wash-example/build/car-wash-example/script_transactions/buy_coin.mvt"
)
}

pub fn car_wash_wash_car() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/car-wash-example/build/car-wash-example/script_transactions/wash_car.mvt"
)
}

// Multiple Signers Example
pub fn multiple_signers_module() -> &'static [u8] {
core::include_bytes!(
Expand All @@ -275,19 +187,29 @@ mod benchmark_only {
)
}

pub fn multiple_signers_init_module() -> &'static [u8] {
core::include_bytes!("assets/move-projects/multiple-signers/build/multiple-signers/script_transactions/init_module.mvt")
}

pub fn multiple_signers_rent_apartment() -> &'static [u8] {
core::include_bytes!("assets/move-projects/multiple-signers/build/multiple-signers/script_transactions/rent_apartment.mvt")
}

pub fn gas_costs_short_cheap_script() -> &'static [u8] {
core::include_bytes!("assets/move-projects/gas-costs/build/gas-costs/script_transactions/short_cheap_script.mvt")
}

pub fn gas_costs_long_cheap_script() -> &'static [u8] {
core::include_bytes!("assets/move-projects/gas-costs/build/gas-costs/script_transactions/long_cheap_script.mvt")
}
impl_gas_costs_cal_fns!(cal_gas_cost_0);
impl_gas_costs_cal_fns!(cal_gas_cost_1);
impl_gas_costs_cal_fns!(cal_gas_cost_2);
impl_gas_costs_cal_fns!(cal_gas_cost_3);
impl_gas_costs_cal_fns!(cal_gas_cost_4);
impl_gas_costs_cal_fns!(cal_gas_cost_5);
impl_gas_costs_cal_fns!(cal_gas_cost_6);
impl_gas_costs_cal_fns!(cal_gas_cost_7);
impl_gas_costs_cal_fns!(cal_gas_cost_8);
impl_gas_costs_cal_fns!(cal_gas_cost_9);
impl_gas_costs_cal_fns!(cal_gas_cost_10);
impl_gas_costs_cal_fns!(cal_gas_cost_11);
impl_gas_costs_cal_fns!(cal_gas_cost_12);
impl_gas_costs_cal_fns!(cal_gas_cost_13);
impl_gas_costs_cal_fns!(cal_gas_cost_14);
impl_gas_costs_cal_fns!(cal_gas_cost_15);
impl_gas_costs_cal_fns!(cal_gas_cost_16);
impl_gas_costs_cal_fns!(cal_gas_cost_17);
impl_gas_costs_cal_fns!(cal_gas_cost_18);
impl_gas_costs_cal_fns!(cal_gas_cost_19);
impl_gas_costs_cal_fns!(cal_gas_cost_20);
impl_gas_costs_cal_fns!(cal_gas_cost_21);
impl_gas_costs_cal_fns!(cal_gas_cost_22);
impl_gas_costs_cal_fns!(cal_gas_cost_23);
impl_gas_costs_cal_fns!(cal_gas_cost_24);
}
2 changes: 1 addition & 1 deletion pallet/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl pallet_move::Config for Test {
type MultisigReqExpireTime = MultisigReqExpireTime;
type MaxScriptSigners = MaxScriptSigners;
type RuntimeEvent = RuntimeEvent;
type WeightInfo = crate::weights::SubstrateWeight<Test>;
type WeightInfo = pallet_move::weights::SubstrateWeight<Test>;
}

/// Test Externalities Builder for an easier test setup.
Expand Down
4 changes: 2 additions & 2 deletions pallet/src/mock_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ mod always_used {
// Reusable constants for test accounts.
pub const BOB_ADDR: &str = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty";
pub const ALICE_ADDR: &str = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
pub const DAVE_ADDR: &str = "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy";
pub const EVE_ADDR: &str = "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw";

/// Creates a native 32-byte address from a given ss58 string.
pub fn account<T: SysConfig + Config>(ss58addr: &str) -> T::AccountId
Expand Down Expand Up @@ -67,6 +65,8 @@ mod tests_only {
use crate::{Config, Pallet};

// Reusable constants for test accounts.
pub const DAVE_ADDR: &str = "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy";
pub const EVE_ADDR: &str = "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw";
// equivalent to 0xCAFE
pub const CAFE_ADDR: &str = "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSv4fmh4G";
// equivalent to 0x1
Expand Down
Loading

0 comments on commit ac61010

Please sign in to comment.