Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating polkadot-runtime-parachains paras_inherent benchmarking to V2 #6606

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
166 changes: 94 additions & 72 deletions polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,50 @@

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
#![cfg(feature = "runtime-benchmarks")]

use super::*;
use crate::{inclusion, ParaId};
use alloc::collections::btree_map::BTreeMap;
use core::cmp::{max, min};
use frame_benchmarking::{benchmarks, impl_benchmark_test_suite};
use frame_benchmarking::v2::*;
use frame_system::RawOrigin;

use polkadot_primitives::v8::GroupIndex;

use crate::builder::BenchBuilder;

benchmarks! {
enter_empty {
let scenario = BenchBuilder::<T>::new()
.build();
#[benchmarks]
mod benchmarks {
use super::*;

#[benchmark]
fn enter_empty() -> Result<(), BenchmarkError> {
let scenario = BenchBuilder::<T>::new().build();

let mut benchmark = scenario.data.clone();

benchmark.bitfields.clear();
benchmark.backed_candidates.clear();
benchmark.disputes.clear();
}: enter(RawOrigin::None, benchmark)
verify {

#[extrinsic_call]
enter(RawOrigin::None, benchmark);

// Assert that the block was not discarded
assert!(Included::<T>::get().is_some());

Ok(())
}

// Variant over `v`, the number of dispute statements in a dispute statement set. This gives the
// weight of a single dispute statement set.
enter_variable_disputes {
// The number of statements needs to be at least a third of the validator set size.
let v in 400..BenchBuilder::<T>::fallback_max_validators();

let scenario = BenchBuilder::<T>::new()
.set_dispute_sessions(&[2])
.build();
// The number of statements needs to be at least a third of the validator set size.
#[benchmark]
fn enter_variable_disputes(
v: Linear<400, { BenchBuilder::<T>::fallback_max_validators() }>,
) -> Result<(), BenchmarkError> {
let scenario = BenchBuilder::<T>::new().set_dispute_sessions(&[2]).build();

let mut benchmark = scenario.data.clone();
let dispute = benchmark.disputes.pop().unwrap();
Expand All @@ -59,8 +67,10 @@ benchmarks! {

benchmark.disputes.push(dispute);
benchmark.disputes.get_mut(0).unwrap().statements.drain(v as usize..);
}: enter(RawOrigin::None, benchmark)
verify {

#[extrinsic_call]
enter(RawOrigin::None, benchmark);

// Assert that the block was not discarded
assert!(Included::<T>::get().is_some());

Expand All @@ -71,14 +81,15 @@ benchmarks! {

// Ensure that the votes are for the correct session
assert_eq!(vote.session, scenario._session);

Ok(())
}

// The weight of one bitfield.
enter_bitfields {
let cores_with_backed: BTreeMap<_, _>
= vec![(0, BenchBuilder::<T>::fallback_max_validators())]
.into_iter()
.collect();
#[benchmark]
fn enter_bitfields() -> Result<(), BenchmarkError> {
let cores_with_backed: BTreeMap<_, _> =
vec![(0, BenchBuilder::<T>::fallback_max_validators())].into_iter().collect();

let scenario = BenchBuilder::<T>::new()
.set_backed_and_concluding_paras(cores_with_backed)
Expand All @@ -92,8 +103,10 @@ benchmarks! {
benchmark.disputes.clear();

benchmark.bitfields.push(bitfield);
}: enter(RawOrigin::None, benchmark)
verify {

#[extrinsic_call]
enter(RawOrigin::None, benchmark);

// Assert that the block was not discarded
assert!(Included::<T>::get().is_some());
// Assert that there are on-chain votes that got scraped
Expand All @@ -102,18 +115,27 @@ benchmarks! {
let vote = onchain_votes.unwrap();
// Ensure that the votes are for the correct session
assert_eq!(vote.session, scenario._session);

Ok(())
}

// Variant over `v`, the amount of validity votes for a backed candidate. This gives the weight
// of a single backed candidate.
enter_backed_candidates_variable {
let v in (BenchBuilder::<T>::fallback_min_backing_votes())
.. max(BenchBuilder::<T>::fallback_min_backing_votes() + 1, BenchBuilder::<T>::fallback_max_validators_per_core());

let cores_with_backed: BTreeMap<_, _>
= vec![(0, v)] // The backed candidate will have `v` validity votes.
.into_iter()
.collect();
#[benchmark]
fn enter_backed_candidates_variable(
v: Linear<
{ BenchBuilder::<T>::fallback_min_backing_votes() },
{
max(
BenchBuilder::<T>::fallback_min_backing_votes() + 1,
BenchBuilder::<T>::fallback_max_validators_per_core(),
)
},
>,
) -> Result<(), BenchmarkError> {
let cores_with_backed: BTreeMap<_, _> = vec![(0, v)] // The backed candidate will have `v` validity votes.
.into_iter()
.collect();

let scenario = BenchBuilder::<T>::new()
.set_backed_in_inherent_paras(cores_with_backed.clone())
Expand All @@ -124,13 +146,18 @@ benchmarks! {
// There is 1 backed,
assert_eq!(benchmark.backed_candidates.len(), 1);
// with `v` validity votes.
let votes = min(scheduler::Pallet::<T>::group_validators(GroupIndex::from(0)).unwrap().len(), v as usize);
let votes = min(
scheduler::Pallet::<T>::group_validators(GroupIndex::from(0)).unwrap().len(),
v as usize,
);
assert_eq!(benchmark.backed_candidates.get(0).unwrap().validity_votes().len(), votes);

benchmark.bitfields.clear();
benchmark.disputes.clear();
}: enter(RawOrigin::None, benchmark)
verify {

#[extrinsic_call]
enter(RawOrigin::None, benchmark);

let max_validators_per_core = BenchBuilder::<T>::fallback_max_validators_per_core();
// Assert that the block was not discarded
assert!(Included::<T>::get().is_some());
Expand All @@ -143,27 +170,27 @@ benchmarks! {
// Ensure that there are an expected number of candidates
let header = BenchBuilder::<T>::header(scenario._block_number);
// Traverse candidates and assert descriptors are as expected
for (para_id, backing_validators) in vote.backing_validators_per_candidate.iter().enumerate() {
for (para_id, backing_validators) in
vote.backing_validators_per_candidate.iter().enumerate()
{
let descriptor = backing_validators.0.descriptor();
assert_eq!(ParaId::from(para_id), descriptor.para_id());
assert_eq!(header.hash(), descriptor.relay_parent());
assert_eq!(backing_validators.1.len(), votes);
}

assert_eq!(
inclusion::PendingAvailability::<T>::iter().count(),
cores_with_backed.len()
);
assert_eq!(inclusion::PendingAvailability::<T>::iter().count(), cores_with_backed.len());

Ok(())
}

enter_backed_candidate_code_upgrade {
#[benchmark]
fn enter_backed_candidate_code_upgrade() -> Result<(), BenchmarkError> {
// For now we always assume worst case code size. In the future we could vary over this.
let v = crate::configuration::ActiveConfig::<T>::get().max_code_size;

let cores_with_backed: BTreeMap<_, _>
= vec![(0, BenchBuilder::<T>::fallback_min_backing_votes())]
.into_iter()
.collect();
let cores_with_backed: BTreeMap<_, _> =
vec![(0, BenchBuilder::<T>::fallback_min_backing_votes())].into_iter().collect();

let scenario = BenchBuilder::<T>::new()
.set_backed_in_inherent_paras(cores_with_backed.clone())
Expand All @@ -174,21 +201,20 @@ benchmarks! {

let votes = min(
scheduler::Pallet::<T>::group_validators(GroupIndex::from(0)).unwrap().len(),
BenchBuilder::<T>::fallback_min_backing_votes() as usize
BenchBuilder::<T>::fallback_min_backing_votes() as usize,
);

// There is 1 backed
assert_eq!(benchmark.backed_candidates.len(), 1);
assert_eq!(
benchmark.backed_candidates.get(0).unwrap().validity_votes().len(),
votes,
);
assert_eq!(benchmark.backed_candidates.get(0).unwrap().validity_votes().len(), votes,);

benchmark.bitfields.clear();
benchmark.disputes.clear();
crate::paras::benchmarking::generate_disordered_upgrades::<T>();
}: enter(RawOrigin::None, benchmark)
verify {

#[extrinsic_call]
enter(RawOrigin::None, benchmark);

let max_validators_per_core = BenchBuilder::<T>::fallback_max_validators_per_core();
// Assert that the block was not discarded
assert!(Included::<T>::get().is_some());
Expand All @@ -201,26 +227,22 @@ benchmarks! {
// Ensure that there are an expected number of candidates
let header = BenchBuilder::<T>::header(scenario._block_number);
// Traverse candidates and assert descriptors are as expected
for (para_id, backing_validators)
in vote.backing_validators_per_candidate.iter().enumerate() {
let descriptor = backing_validators.0.descriptor();
assert_eq!(ParaId::from(para_id), descriptor.para_id());
assert_eq!(header.hash(), descriptor.relay_parent());
assert_eq!(
backing_validators.1.len(),
votes,
);
}

assert_eq!(
inclusion::PendingAvailability::<T>::iter().count(),
cores_with_backed.len()
);
for (para_id, backing_validators) in
vote.backing_validators_per_candidate.iter().enumerate()
{
let descriptor = backing_validators.0.descriptor();
assert_eq!(ParaId::from(para_id), descriptor.para_id());
assert_eq!(header.hash(), descriptor.relay_parent());
assert_eq!(backing_validators.1.len(), votes,);
}

assert_eq!(inclusion::PendingAvailability::<T>::iter().count(), cores_with_backed.len());
Ok(())
}
}

impl_benchmark_test_suite!(
Pallet,
crate::mock::new_test_ext(Default::default()),
crate::mock::Test
);
impl_benchmark_test_suite! {
Pallet,
crate::mock::new_test_ext(Default::default()),
crate::mock::Test
}
}