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

Collective: Benchmark with greater MaxProposals #12454

Merged
merged 19 commits into from
Nov 14, 2022
74 changes: 43 additions & 31 deletions frame/collective/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ fn assert_last_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
}

fn id_to_remark_data<T: Config<I>, I: 'static>(id: u32, length: usize) -> Vec<u8> {
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
let mut remark_data: Vec<u8> = vec![];
let mut value = id;
let mut counter = 0;
while value > u8::MAX as u32 {
value -= u8::MAX as u32;
remark_data.push(u8::MAX);
counter += 1;
}
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
remark_data.push(value.try_into().unwrap());
counter += 1;
for _i in counter..length {
// fill the rest of the array with zeros.
remark_data.push(0);
}
remark_data
}

benchmarks_instance_pallet! {
set_members {
let m in 0 .. T::MaxMembers::get();
Expand Down Expand Up @@ -64,9 +82,7 @@ benchmarks_instance_pallet! {
let length = 100;
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark {
remark: vec![i as u8; length]
}.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, length) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(old_members.last().unwrap().clone()).into(),
threshold,
Expand Down Expand Up @@ -105,10 +121,10 @@ benchmarks_instance_pallet! {
}

execute {
let b in 1 .. MAX_BYTES;
let b in 2 .. MAX_BYTES;
let m in 1 .. T::MaxMembers::get();

let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);
Szegoo marked this conversation as resolved.
Show resolved Hide resolved

// Construct `members`.
let mut members = vec![];
Expand All @@ -122,7 +138,7 @@ benchmarks_instance_pallet! {

Collective::<T, I>::set_members(SystemOrigin::Root.into(), members, None, T::MaxMembers::get())?;

let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![1; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(1, b as usize) }.into();

}: _(SystemOrigin::Signed(caller), Box::new(proposal.clone()), bytes_in_storage)
verify {
Expand All @@ -135,10 +151,10 @@ benchmarks_instance_pallet! {

// This tests when execution would happen immediately after proposal
propose_execute {
let b in 1 .. MAX_BYTES;
let b in 2 .. MAX_BYTES;
let m in 1 .. T::MaxMembers::get();

let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -152,7 +168,7 @@ benchmarks_instance_pallet! {

Collective::<T, I>::set_members(SystemOrigin::Root.into(), members, None, T::MaxMembers::get())?;

let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![1; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(1, b as usize) }.into();
let threshold = 1;

}: propose(SystemOrigin::Signed(caller), threshold, Box::new(proposal.clone()), bytes_in_storage)
Expand All @@ -166,11 +182,11 @@ benchmarks_instance_pallet! {

// This tests when proposal is created and queued as "proposed"
propose_proposed {
let b in 1 .. MAX_BYTES;
let b in 2 .. MAX_BYTES;
let m in 2 .. T::MaxMembers::get();
let p in 1 .. T::MaxProposals::get();

let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -186,7 +202,7 @@ benchmarks_instance_pallet! {
// Add previous proposals.
for i in 0 .. p - 1 {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, b as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(caller.clone()).into(),
threshold,
Expand All @@ -197,7 +213,7 @@ benchmarks_instance_pallet! {

assert_eq!(Collective::<T, I>::proposals().len(), (p - 1) as usize);

let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![p as u8; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(p, b as usize) }.into();

}: propose(SystemOrigin::Signed(caller.clone()), threshold, Box::new(proposal.clone()), bytes_in_storage)
verify {
Expand All @@ -213,7 +229,7 @@ benchmarks_instance_pallet! {

let p = T::MaxProposals::get();
let b = MAX_BYTES;
let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -234,7 +250,7 @@ benchmarks_instance_pallet! {
let mut last_hash = T::Hash::default();
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, b as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(proposer.clone()).into(),
threshold,
Expand Down Expand Up @@ -288,7 +304,7 @@ benchmarks_instance_pallet! {
let p in 1 .. T::MaxProposals::get();

let bytes = 100;
let bytes_in_storage = bytes + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (bytes + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -309,9 +325,7 @@ benchmarks_instance_pallet! {
let mut last_hash = T::Hash::default();
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark {
remark: vec![i as u8; bytes as usize]
}.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, bytes as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(proposer.clone()).into(),
threshold,
Expand Down Expand Up @@ -364,12 +378,12 @@ benchmarks_instance_pallet! {
}

close_early_approved {
let b in 1 .. MAX_BYTES;
let b in 2 .. MAX_BYTES;
// We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`)
let m in 4 .. T::MaxMembers::get();
let p in 1 .. T::MaxProposals::get();

let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -388,7 +402,7 @@ benchmarks_instance_pallet! {
let mut last_hash = T::Hash::default();
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, b as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(caller.clone()).into(),
threshold,
Expand Down Expand Up @@ -450,7 +464,7 @@ benchmarks_instance_pallet! {
let p in 1 .. T::MaxProposals::get();

let bytes = 100;
let bytes_in_storage = bytes + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (bytes + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -474,9 +488,7 @@ benchmarks_instance_pallet! {
let mut last_hash = T::Hash::default();
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark {
remark: vec![i as u8; bytes as usize]
}.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, bytes as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(caller.clone()).into(),
threshold,
Expand Down Expand Up @@ -519,12 +531,12 @@ benchmarks_instance_pallet! {
}

close_approved {
let b in 1 .. MAX_BYTES;
let b in 2 .. MAX_BYTES;
Copy link
Member

Choose a reason for hiding this comment

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

Why these changes?

Copy link
Contributor Author

@Szegoo Szegoo Nov 14, 2022

Choose a reason for hiding this comment

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

The goal of this PR was to be able to set the MaxProposal to a value higher than 255. In the benchmarks, we use the remark function to represent a proposal. Because we cannot have two identical proposals what we did until now is make the remark data be a variable number repeated a number of times(b times). This comes with a limit since the remark data is a Vec<u8> so it cannot accept a number greater than 255. To fix this we use little-endian to encode these greater numbers. So to represent a number greater than 255 we need a vector that is longer than 1. That is why we updated the range of b so that it starts from 2. @bkchr

I hope the explanation makes sense :)

Copy link
Member

Choose a reason for hiding this comment

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

Then it should be changed to 4, because MaxMembers is an u32 which would lead to duplicate proposals when using more than 65k max members. You should also leave some comment on why we start at 4.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Hmm okay 🙈

Copy link
Member

Choose a reason for hiding this comment

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

I'm not happy with this, but okay :P

// We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`)
let m in 4 .. T::MaxMembers::get();
let p in 1 .. T::MaxProposals::get();

let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -548,7 +560,7 @@ benchmarks_instance_pallet! {
let mut last_hash = T::Hash::default();
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, b as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(caller.clone()).into(),
threshold,
Expand Down Expand Up @@ -595,7 +607,7 @@ benchmarks_instance_pallet! {

let m = 3;
let b = MAX_BYTES;
let bytes_in_storage = b + size_of::<u32>() as u32;
let bytes_in_storage = 4 * (b + size_of::<u32>() as u32);

// Construct `members`.
let mut members = vec![];
Expand All @@ -619,7 +631,7 @@ benchmarks_instance_pallet! {
let mut last_hash = T::Hash::default();
for i in 0 .. p {
// Proposals should be different so that different proposal hashes are generated
let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
let proposal: T::Proposal = SystemCall::<T>::remark { remark: id_to_remark_data::<T, I>(i, b as usize) }.into();
Collective::<T, I>::propose(
SystemOrigin::Signed(caller.clone()).into(),
threshold,
Expand Down