Files
pezkuwi-sdk/pezcumulus/pezpallets/xcmp-queue/src/benchmarking.rs
T
pezkuwichain b6d35f6faf chore: add Dijital Kurdistan Tech Institute to copyright headers
Updated 4763 files with dual copyright:
- Parity Technologies (UK) Ltd.
- Dijital Kurdistan Tech Institute
2025-12-27 21:28:36 +03:00

342 lines
8.4 KiB
Rust

// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Benchmarking setup for pezcumulus-pezpallet-xcmp-queue
use crate::{weights_ext::get_average_page_pos, *};
use alloc::vec;
use codec::DecodeAll;
use pezframe_benchmarking::v2::*;
use pezframe_support::{assert_ok, traits::Hooks};
use pezframe_system::RawOrigin;
use xcm::MAX_INSTRUCTIONS_TO_DECODE;
#[benchmarks]
mod benchmarks {
use super::*;
/// Modify any of the `QueueConfig` fields with a new `u32` value.
///
/// Used as weight for:
/// - update_suspend_threshold
/// - update_drop_threshold
/// - update_resume_threshold
#[benchmark]
fn set_config_with_u32() {
#[extrinsic_call]
Pezpallet::<T>::update_resume_threshold(RawOrigin::Root, 1);
}
/// Add a XCMP message of `n` bytes to the message queue.
///
/// The message will be added on a new page and also, the `BookState` will be added
/// to the ready ring.
#[benchmark]
fn enqueue_n_bytes_xcmp_message(n: Linear<0, { MaxXcmpMessageLenOf::<T>::get() }>) {
#[cfg(test)]
{
mock::EnqueuedMessages::set(vec![]);
}
let msg = BoundedVec::try_from(vec![0; n as usize]).unwrap();
#[cfg(not(test))]
let fp_before = T::XcmpQueue::footprint(0.into());
#[block]
{
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&[msg.as_bounded_slice()],
true,
&mut WeightMeter::new()
));
}
#[cfg(not(test))]
{
let fp_after = T::XcmpQueue::footprint(0.into());
assert_eq!(fp_after.ready_pages, fp_before.ready_pages + 1);
}
}
/// Add `n` XCMP message of 0 bytes to the message queue.
///
/// Only for the first message a new page will be created and the `BookState` will be added
/// to the ready ring.
#[benchmark]
fn enqueue_n_empty_xcmp_messages(n: Linear<0, 1000>) {
#[cfg(test)]
{
mock::EnqueuedMessages::set(vec![]);
<QueueConfig<T>>::set(QueueConfigData {
suspend_threshold: 1100,
drop_threshold: 1100,
resume_threshold: 1100,
});
}
let msg = BoundedVec::new();
let msgs = vec![msg.as_bounded_slice(); n as usize];
#[cfg(not(test))]
let fp_before = T::XcmpQueue::footprint(0.into());
#[block]
{
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&msgs,
true,
&mut WeightMeter::new()
));
}
#[cfg(not(test))]
{
let fp_after = T::XcmpQueue::footprint(0.into());
if !msgs.is_empty() {
assert_eq!(fp_after.ready_pages, fp_before.ready_pages + 1);
}
}
}
/// Add an XCMP message of 0 bytes to the message queue at the provided position
/// on an existing page.
#[benchmark(pov_mode = Measured)]
fn enqueue_empty_xcmp_message_at(
n: Linear<0, { crate::MaxXcmpMessageLenOf::<T>::get() - 10 }>,
) {
#[cfg(test)]
{
mock::EnqueuedMessages::set(vec![]);
}
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&[BoundedVec::try_from(vec![0; n as usize]).unwrap().as_bounded_slice()],
true,
&mut WeightMeter::new()
));
#[cfg(not(test))]
let fp_before = T::XcmpQueue::footprint(0.into());
#[block]
{
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&[BoundedVec::new().as_bounded_slice()],
true,
&mut WeightMeter::new()
));
}
#[cfg(not(test))]
{
let fp_after = T::XcmpQueue::footprint(0.into());
assert_eq!(fp_after.ready_pages, fp_before.ready_pages);
}
}
/// Add `n` pages to the message queue.
///
/// We add one page by enqueueing a maximal size message which fills it.
#[benchmark]
fn enqueue_n_full_pages(n: Linear<0, 100>) {
#[cfg(test)]
{
mock::EnqueuedMessages::set(vec![]);
}
<QueueConfig<T>>::set(QueueConfigData {
suspend_threshold: 200,
drop_threshold: 200,
resume_threshold: 200,
});
let max_msg_len = MaxXcmpMessageLenOf::<T>::get() as usize;
let mut msgs = vec![];
for _i in 0..n {
let msg = BoundedVec::try_from(vec![0; max_msg_len]).unwrap();
msgs.push(msg);
}
#[cfg(not(test))]
let fp_before = T::XcmpQueue::footprint(0.into());
#[block]
{
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&msgs.iter().map(|msg| msg.as_bounded_slice()).collect::<Vec<_>>(),
true,
&mut WeightMeter::new()
));
}
#[cfg(not(test))]
{
let fp_after = T::XcmpQueue::footprint(0.into());
assert_eq!(fp_after.ready_pages, fp_before.ready_pages + n);
}
}
#[benchmark(pov_mode = Measured)]
fn enqueue_1000_small_xcmp_messages() {
#[cfg(test)]
{
<QueueConfig<T>>::set(QueueConfigData {
suspend_threshold: 1100,
drop_threshold: 1100,
resume_threshold: 1100,
});
}
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&[BoundedVec::try_from(vec![
0;
get_average_page_pos(MaxXcmpMessageLenOf::<T>::get())
as usize
])
.unwrap()
.as_bounded_slice()],
true,
&mut WeightMeter::new()
));
let mut msgs = vec![];
for _i in 0..1000 {
msgs.push(BoundedVec::try_from(vec![0; 3]).unwrap());
}
#[cfg(not(test))]
let fp_before = T::XcmpQueue::footprint(0.into());
#[block]
{
assert_ok!(Pezpallet::<T>::enqueue_xcmp_messages(
0.into(),
&msgs.iter().map(|msg| msg.as_bounded_slice()).collect::<Vec<_>>(),
true,
&mut WeightMeter::new()
));
}
#[cfg(not(test))]
{
let fp_after = T::XcmpQueue::footprint(0.into());
assert_eq!(fp_after.ready_pages, fp_before.ready_pages);
}
}
#[benchmark]
fn suspend_channel() {
let para = 123.into();
let data = ChannelSignal::Suspend.encode();
#[block]
{
ChannelSignal::decode_all(&mut &data[..]).unwrap();
Pezpallet::<T>::suspend_channel(para);
}
assert_eq!(
OutboundXcmpStatus::<T>::get()
.iter()
.find(|p| p.recipient == para)
.unwrap()
.state,
OutboundState::Suspended
);
}
#[benchmark]
fn resume_channel() {
let para = 123.into();
let data = ChannelSignal::Resume.encode();
Pezpallet::<T>::suspend_channel(para);
#[block]
{
ChannelSignal::decode_all(&mut &data[..]).unwrap();
Pezpallet::<T>::resume_channel(para);
}
assert!(
OutboundXcmpStatus::<T>::get().iter().all(|p| p.recipient != para),
"No messages in the channel; therefore removed."
);
}
/// Split a singular XCM.
#[benchmark]
fn take_first_concatenated_xcm(
n: Linear<0, { MAX_INSTRUCTIONS_TO_DECODE as u32 - MAX_XCM_DECODE_DEPTH }>,
) {
let mut xcm = Xcm::<T>(vec![ClearOrigin; n as usize]);
for _ in 0..MAX_XCM_DECODE_DEPTH - 1 {
xcm = Xcm::<T>(vec![Instruction::SetAppendix(xcm)]);
}
let data = VersionedXcm::<T>::from(xcm).encode();
#[block]
{
Pezpallet::<T>::take_first_concatenated_xcm(&mut &data[..], &mut WeightMeter::new())
.unwrap();
}
}
/// Benchmark the migration for a maximal sized message.
#[benchmark]
fn on_idle_good_msg() {
use migration::v3;
let block = 5;
let para = ParaId::from(4);
let message = vec![123u8; MaxXcmpMessageLenOf::<T>::get() as usize];
let message_metadata = vec![(block, XcmpMessageFormat::ConcatenatedVersionedXcm)];
v3::InboundXcmpMessages::<T>::insert(para, block, message);
v3::InboundXcmpStatus::<T>::set(Some(vec![v3::InboundChannelDetails {
sender: para,
state: v3::InboundState::Ok,
message_metadata,
}]));
#[block]
{
Pezpallet::<T>::on_idle(0u32.into(), Weight::MAX);
}
}
/// Benchmark the migration with a 64 KiB message that will not be possible to enqueue.
#[benchmark]
fn on_idle_large_msg() {
use migration::v3;
let block = 5;
let para = ParaId::from(4);
let message = vec![123u8; 1 << 16]; // 64 KiB message
let message_metadata = vec![(block, XcmpMessageFormat::ConcatenatedVersionedXcm)];
v3::InboundXcmpMessages::<T>::insert(para, block, message);
v3::InboundXcmpStatus::<T>::set(Some(vec![v3::InboundChannelDetails {
sender: para,
state: v3::InboundState::Ok,
message_metadata,
}]));
#[block]
{
Pezpallet::<T>::on_idle(0u32.into(), Weight::MAX);
}
}
impl_benchmark_test_suite!(Pezpallet, crate::mock::new_test_ext(), crate::mock::Test);
}