Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Create benchmarks for XCM instructions introduced in v3 #4564

Merged
merged 16 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions runtime/westend/src/weights/xcm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,34 @@ impl<Call> XcmWeightInfo<Call> for WestendXcmWeight<Call> {
fn unsubscribe_version() -> Weight {
XcmGeneric::<Runtime>::unsubscribe_version()
}
fn burn_asset(assets: &MultiAssets) -> Weight {
assets.weigh_multi_assets(XcmGeneric::<Runtime>::burn_asset())
}
fn expect_asset(assets: &MultiAssets) -> Weight {
assets.weigh_multi_assets(XcmGeneric::<Runtime>::expect_asset())
}
fn expect_origin(_origin: &Option<MultiLocation>) -> Weight {
XcmGeneric::<Runtime>::expect_origin()
}
fn expect_error(_error: &Option<(u32, XcmError)>) -> Weight {
XcmGeneric::<Runtime>::expect_error()
}
fn query_pallet(_module_name: &Vec<u8>, _response_info: &QueryResponseInfo) -> Weight {
XcmGeneric::<Runtime>::query_pallet()
}
fn expect_pallet(
_index: &u32,
_name: &Vec<u8>,
_module_name: &Vec<u8>,
_crate_major: &u32,
_min_crate_minor: &u32,
) -> Weight {
XcmGeneric::<Runtime>::expect_pallet()
}
fn report_transact_status(_response_info: &QueryResponseInfo) -> Weight {
XcmGeneric::<Runtime>::report_transact_status()
}
fn clear_transact_status() -> Weight {
XcmGeneric::<Runtime>::clear_transact_status()
}
}
83 changes: 64 additions & 19 deletions runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
Expand All @@ -17,7 +17,7 @@
//! Autogenerated weights for `pallet_xcm_benchmarks::generic`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2021-12-01, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! DATE: 2021-12-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 128

// Executed Command:
Expand Down Expand Up @@ -45,56 +45,63 @@ use sp_std::marker::PhantomData;
/// Weights for `pallet_xcm_benchmarks::generic`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo<T> {
pub fn report_holding() -> Weight {
1_000_000_000
// Storage: XcmPallet SupportedVersion (r:1 w:0)
// Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1)
// Storage: XcmPallet SafeXcmVersion (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
pub(crate) fn report_holding() -> Weight {
(35_446_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
pub(crate) fn buy_execution() -> Weight {
(5_922_000 as Weight)
(5_228_000 as Weight)
}
// Storage: XcmPallet Queries (r:1 w:0)
pub(crate) fn query_response() -> Weight {
(20_625_000 as Weight)
(18_708_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
}
pub(crate) fn transact() -> Weight {
(22_198_000 as Weight)
(20_401_000 as Weight)
}
pub(crate) fn refund_surplus() -> Weight {
(6_122_000 as Weight)
(5_238_000 as Weight)
}
pub(crate) fn set_error_handler() -> Weight {
(5_758_000 as Weight)
(5_104_000 as Weight)
}
pub(crate) fn set_appendix() -> Weight {
(5_764_000 as Weight)
(5_095_000 as Weight)
}
pub(crate) fn clear_error() -> Weight {
(5_679_000 as Weight)
(5_010_000 as Weight)
}
pub(crate) fn descend_origin() -> Weight {
(7_206_000 as Weight)
(6_368_000 as Weight)
}
pub(crate) fn clear_origin() -> Weight {
(5_738_000 as Weight)
(5_011_000 as Weight)
}
// Storage: XcmPallet SupportedVersion (r:1 w:0)
// Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1)
// Storage: XcmPallet SafeXcmVersion (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
pub(crate) fn report_error() -> Weight {
(31_512_000 as Weight)
(27_823_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
// Storage: XcmPallet AssetTraps (r:1 w:1)
pub(crate) fn claim_asset() -> Weight {
(13_594_000 as Weight)
(12_402_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
pub(crate) fn trap() -> Weight {
(5_745_000 as Weight)
(5_022_000 as Weight)
}
// Storage: XcmPallet VersionNotifyTargets (r:1 w:1)
// Storage: XcmPallet SupportedVersion (r:1 w:0)
Expand All @@ -103,13 +110,13 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
pub(crate) fn subscribe_version() -> Weight {
(38_138_000 as Weight)
(32_492_000 as Weight)
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: XcmPallet VersionNotifyTargets (r:0 w:1)
pub(crate) fn unsubscribe_version() -> Weight {
(9_127_000 as Weight)
(7_777_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: XcmPallet SupportedVersion (r:1 w:0)
Expand All @@ -118,8 +125,46 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
pub(crate) fn initiate_reserve_withdraw() -> Weight {
(41_443_000 as Weight)
(37_066_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
pub(crate) fn burn_asset() -> Weight {
(7_935_000 as Weight)
}
pub(crate) fn expect_asset() -> Weight {
(5_237_000 as Weight)
}
pub(crate) fn expect_origin() -> Weight {
(5_245_000 as Weight)
}
pub(crate) fn expect_error() -> Weight {
(5_062_000 as Weight)
}
// Storage: XcmPallet SupportedVersion (r:1 w:0)
// Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1)
// Storage: XcmPallet SafeXcmVersion (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
pub(crate) fn query_pallet() -> Weight {
(28_876_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
pub(crate) fn expect_pallet() -> Weight {
(5_526_000 as Weight)
}
// Storage: XcmPallet SupportedVersion (r:1 w:0)
// Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1)
// Storage: XcmPallet SafeXcmVersion (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
pub(crate) fn report_transact_status() -> Weight {
(27_889_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
pub(crate) fn clear_transact_status() -> Weight {
(5_100_000 as Weight)
}
}
2 changes: 1 addition & 1 deletion xcm/pallet-xcm-benchmarks/src/fungible/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl xcm_executor::Config for XcmConfig {
type AssetTrap = ();
type AssetClaims = ();
type SubscriptionService = ();
type PalletInstancesInfo = ();
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
}

Expand Down
143 changes: 135 additions & 8 deletions xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ use frame_benchmarking::{benchmarks, BenchmarkError};
use frame_support::dispatch::GetDispatchInfo;
use sp_std::vec;
use xcm::{
latest::{prelude::*, MultiAssets},
latest::{prelude::*, MaybeErrorCode, MultiAssets},
DoubleEncoded,
};
use xcm_executor::ExecutorError;

benchmarks! {
report_holding {
Expand Down Expand Up @@ -254,12 +255,10 @@ benchmarks! {
} : {
_result = executor.execute(xcm);
} verify {
match _result {
Err(error) if error.xcm_error == XcmError::Trap(10) => {
// This is the success condition
},
_ => Err("xcm trap did not return the expected error")?
};
assert!(matches!(_result, Err(ExecutorError {
xcm_error: XcmError::Trap(10),
..
})));
}

subscribe_version {
Expand Down Expand Up @@ -306,13 +305,141 @@ benchmarks! {
executor.holding = holding.into();
let instruction = Instruction::InitiateReserveWithdraw { assets: assets_filter, reserve, xcm: Xcm(vec![]) };
let xcm = Xcm(vec![instruction]);
}:{
}: {
executor.execute(xcm)?;
} verify {
// The execute completing successfully is as good as we can check.
// TODO: Potentially add new trait to XcmSender to detect a queued outgoing message. #4426
}

burn_asset {
let holding = T::worst_case_holding(0);
let assets = holding.clone();

let mut executor = new_executor::<T>(Default::default());
executor.holding = holding.into();

let instruction = Instruction::BurnAsset(assets.into());
let xcm = Xcm(vec![instruction]);
}: {
executor.execute(xcm)?;
} verify {
assert!(executor.holding.is_empty());
}

expect_asset {
let holding = T::worst_case_holding(0);
let assets = holding.clone();

let mut executor = new_executor::<T>(Default::default());
executor.holding = holding.into();

let instruction = Instruction::ExpectAsset(assets.into());
let xcm = Xcm(vec![instruction]);
}: {
executor.execute(xcm)?;
} verify {
// `execute` completing successfully is as good as we can check.
}

expect_origin {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simple comment here that worst case scenario is when the expected origin call fails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it actually is -- I'm using the failure case here because it's easier to verify that it worked than the success case, since the success case looks practically identical to any other success case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't success here means that the expected origin matches? so literally only one input could give a success output?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I can't do a match against the result. If we are to treat the entire XCM executor as a blackbox, then the success case is not distinguishable from the "do nothing" case, since both of them emit no observable result, and hence I've chosen the failure case.

let expected_origin = Parent.into();
let mut executor = new_executor::<T>(Default::default());

let instruction = Instruction::ExpectOrigin(Some(expected_origin));
let xcm = Xcm(vec![instruction]);
let mut _result = Ok(());
}: {
_result = executor.execute(xcm);
} verify {
assert!(matches!(_result, Err(ExecutorError {
xcm_error: XcmError::ExpectationFalse,
..
})));
}

expect_error {
KiChjang marked this conversation as resolved.
Show resolved Hide resolved
let mut executor = new_executor::<T>(Default::default());
executor.error = Some((3u32, XcmError::Overflow));

let instruction = Instruction::ExpectError(None);
let xcm = Xcm(vec![instruction]);
let mut _result = Ok(());
}: {
_result = executor.execute(xcm);
} verify {
assert!(matches!(_result, Err(ExecutorError {
xcm_error: XcmError::ExpectationFalse,
..
})));
}

query_pallet {
let query_id = Default::default();
let destination = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
let max_weight = Default::default();
let mut executor = new_executor::<T>(Default::default());

let instruction = Instruction::QueryPallet {
module_name: b"frame_system".to_vec(),
kianenigma marked this conversation as resolved.
Show resolved Hide resolved
response_info: QueryResponseInfo { destination, query_id, max_weight },
};
let xcm = Xcm(vec![instruction]);
}: {
executor.execute(xcm)?;
} verify {
// TODO: Potentially add new trait to XcmSender to detect a queued outgoing message. #4426
}

expect_pallet {
let mut executor = new_executor::<T>(Default::default());

let instruction = Instruction::ExpectPallet {
index: 0,
name: b"System".to_vec(),
module_name: b"frame_system".to_vec(),
crate_major: 4,
min_crate_minor: 0,
Comment on lines +398 to +402
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to make this test more adaptable?

For example, you will easily fail this benchmark when the crate version increments. Better to query some value you know will succeed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well hmm, I guess I could create a dummy pallet, import it into the runtime and give it a fixed index location.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would also need to be generic for any runtime we benchmark this on too, so making a custom pallet is not a good choice.

};
let xcm = Xcm(vec![instruction]);
}: {
executor.execute(xcm)?;
} verify {
// the execution succeeding is all we need to verify this xcm was successful
}

report_transact_status {
let query_id = Default::default();
let destination = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
let max_weight = Default::default();

let mut executor = new_executor::<T>(Default::default());
executor.transact_status = MaybeErrorCode::Error(b"MyError".to_vec());

let instruction = Instruction::ReportTransactStatus(QueryResponseInfo {
query_id,
destination,
max_weight,
});
let xcm = Xcm(vec![instruction]);
}: {
executor.execute(xcm)?;
} verify {
// TODO: Potentially add new trait to XcmSender to detect a queued outgoing message. #4426
}

clear_transact_status {
let mut executor = new_executor::<T>(Default::default());
executor.transact_status = MaybeErrorCode::Error(b"MyError".to_vec());

let instruction = Instruction::ClearTransactStatus;
let xcm = Xcm(vec![instruction]);
}: {
executor.execute(xcm)?;
} verify {
assert_eq!(executor.transact_status, MaybeErrorCode::Success);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a note for this PR, but it is strange to me the transaction status defaults to success versus some kind of "unreported'

}

impl_benchmark_test_suite!(
Pallet,
crate::generic::mock::new_test_ext(),
Expand Down
2 changes: 1 addition & 1 deletion xcm/pallet-xcm-benchmarks/src/generic/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl xcm_executor::Config for XcmConfig {
type AssetTrap = TestAssetTrap;
type AssetClaims = TestAssetTrap;
type SubscriptionService = TestSubscriptionService;
type PalletInstancesInfo = ();
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
}

Expand Down
Loading