From ad340bf5cc11f34d5562a61d809b5cccee3dfc0b Mon Sep 17 00:00:00 2001 From: Michael Turner Date: Wed, 17 Apr 2024 11:35:25 -0400 Subject: [PATCH 1/3] Add benchmarks for bonded mapping access --- synthesizer/Cargo.toml | 5 ++ synthesizer/benches/bond_mapping.rs | 121 ++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 synthesizer/benches/bond_mapping.rs diff --git a/synthesizer/Cargo.toml b/synthesizer/Cargo.toml index 13167e27de..c53344aa52 100644 --- a/synthesizer/Cargo.toml +++ b/synthesizer/Cargo.toml @@ -60,6 +60,11 @@ wasm = [ "synthesizer-snark/wasm" ] +[[bench]] +name = "bond_mapping" +path = "benches/bond_mapping.rs" +harness = false + [[bench]] name = "kary_merkle_tree" path = "benches/kary_merkle_tree.rs" diff --git a/synthesizer/benches/bond_mapping.rs b/synthesizer/benches/bond_mapping.rs new file mode 100644 index 0000000000..25db291cdd --- /dev/null +++ b/synthesizer/benches/bond_mapping.rs @@ -0,0 +1,121 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the snarkVM library. + +// 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. + +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the snarkVM library. + +// 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. + +#[macro_use] +extern crate criterion; + +use console::{ + account::{Address, Field, PrivateKey}, + collections::U64, + network::MainnetV0, + program::{Identifier, Literal, Plaintext, ProgramID, Value}, +}; +use ledger_committee::{MAX_DELEGATORS, MIN_DELEGATOR_STAKE}; +#[cfg(not(feature = "rocks"))] +use ledger_store::helpers::memory::ConsensusMemory; +#[cfg(feature = "rocks")] +use ledger_store::helpers::rocksdb::ConsensusDB; +use ledger_store::ConsensusStore; +use snarkvm_synthesizer::VM; + +use criterion::Criterion; +use indexmap::indexmap; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use std::{str::FromStr, time::Duration}; + +pub type CurrentNetwork = MainnetV0; +#[cfg(feature = "rocks")] +pub type CurrentStorage = ConsensusDB; +#[cfg(not(feature = "rocks"))] +pub type CurrentStorage = ConsensusMemory; + +fn bench_bonded_mappings(c: &mut Criterion) { + // Construct the credits.aleo program ID. + let credits_program_id = ProgramID::from_str("credits.aleo").unwrap(); + // Construct the bonded mapping name. + let bonded_mapping = Identifier::from_str("bonded").unwrap(); + // Construct the bonded_state struct identifiers. + let validator_identifier = Identifier::from_str("validator").expect("Failed to parse 'validator'"); + let microcredits_identifier = Identifier::from_str("microcredits").expect("Failed to parse 'microcredits'"); + // Create a DB store for the consensus. + let store = ConsensusStore::::open(None).unwrap(); + // Create a VM from the store. + let vm = VM::from(store).unwrap(); + // Get a sample validator address. + let validator_address = + Address::from_str("aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px").unwrap(); + + // Generate 100_000 bonded mapping entries. + let bonded_map = (0..(MAX_DELEGATORS as u64)) + .into_par_iter() + .map(|i| { + // Generate addresses for the stakers. + let private_key = PrivateKey::try_from(Field::from_u64(i)).unwrap(); + let staker_address = Address::::try_from(&private_key).unwrap(); + + // Create the bonded state. + let bonded_state = indexmap! { + validator_identifier => Plaintext::from(Literal::Address(validator_address)), + microcredits_identifier => Plaintext::from(Literal::U64(U64::new(MIN_DELEGATOR_STAKE))), + }; + ( + Plaintext::from(Literal::Address(staker_address)), + Value::Plaintext(Plaintext::Struct(bonded_state, Default::default())), + ) + }) + .collect::, Value)>>(); + + // Insert 100_000 entries into the bonded mapping. + vm.finalize_store().replace_mapping(credits_program_id, bonded_mapping, bonded_map).unwrap(); + + // Get a key to access the bonded mapping with. + let private_key = PrivateKey::try_from(Field::from_u64(0)).unwrap(); + let staker_address = Address::::try_from(&private_key).unwrap(); + let key = Plaintext::from(Literal::Address(staker_address)); + + // Benchmark get_value_speculative on the bonded mapping at 100_000 entries. + c.bench_function("bonded mapping - get_value_speculative - 100_000 entries", |b| { + b.iter(|| { + let _value = vm.finalize_store().get_value_speculative(credits_program_id, bonded_mapping, &key).unwrap(); + }) + }); + + // Benchmark get_value_confirmed on the bonded mapping at 100_000 entries. + c.bench_function("bonded mapping - get_value_confirmed - 100_000 entries", |b| { + b.iter(|| { + let _value = vm.finalize_store().get_value_confirmed(credits_program_id, bonded_mapping, &key).unwrap(); + }) + }); +} + +criterion_group! { + name = mappings; + config = Criterion::default().sample_size(100).measurement_time(Duration::from_secs(10)); + targets = bench_bonded_mappings +} +criterion_main!(mappings); From 4e5d9843452d097f481e12ecc5a3d17605c31971 Mon Sep 17 00:00:00 2001 From: Michael Turner Date: Fri, 19 Apr 2024 07:09:25 -0400 Subject: [PATCH 2/3] Bench get_value_speculative/confirmed on bonded mapping at increasing intervals --- synthesizer/benches/bond_mapping.rs | 68 +++++++++++++---------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/synthesizer/benches/bond_mapping.rs b/synthesizer/benches/bond_mapping.rs index 25db291cdd..fa877ee933 100644 --- a/synthesizer/benches/bond_mapping.rs +++ b/synthesizer/benches/bond_mapping.rs @@ -12,20 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Copyright (C) 2019-2023 Aleo Systems Inc. -// This file is part of the snarkVM library. - -// 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. - #[macro_use] extern crate criterion; @@ -42,9 +28,11 @@ use ledger_store::helpers::memory::ConsensusMemory; use ledger_store::helpers::rocksdb::ConsensusDB; use ledger_store::ConsensusStore; use snarkvm_synthesizer::VM; +use utilities::cfg_into_iter; use criterion::Criterion; use indexmap::indexmap; +#[cfg(not(feature = "serial"))] use rayon::iter::{IntoParallelIterator, ParallelIterator}; use std::{str::FromStr, time::Duration}; @@ -54,27 +42,28 @@ pub type CurrentStorage = ConsensusDB; #[cfg(not(feature = "rocks"))] pub type CurrentStorage = ConsensusMemory; +pub const BONDED_INTERVALS: &[usize; 7] = &[10, 5_000, 10_000, 20_000, 40_000, 80_000, 100_000]; + fn bench_bonded_mappings(c: &mut Criterion) { // Construct the credits.aleo program ID. let credits_program_id = ProgramID::from_str("credits.aleo").unwrap(); // Construct the bonded mapping name. let bonded_mapping = Identifier::from_str("bonded").unwrap(); - // Construct the bonded_state struct identifiers. - let validator_identifier = Identifier::from_str("validator").expect("Failed to parse 'validator'"); - let microcredits_identifier = Identifier::from_str("microcredits").expect("Failed to parse 'microcredits'"); + // Construct the bond_state identifiers. + let validator_identifier = Identifier::from_str("validator").unwrap(); + let microcredits_identifier = Identifier::from_str("microcredits").unwrap(); // Create a DB store for the consensus. let store = ConsensusStore::::open(None).unwrap(); // Create a VM from the store. let vm = VM::from(store).unwrap(); - // Get a sample validator address. + // Create a sample validator address. let validator_address = Address::from_str("aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px").unwrap(); // Generate 100_000 bonded mapping entries. - let bonded_map = (0..(MAX_DELEGATORS as u64)) - .into_par_iter() + let bonded_map = cfg_into_iter!((0..(MAX_DELEGATORS as u64))) .map(|i| { - // Generate addresses for the stakers. + // Generate a staker address. let private_key = PrivateKey::try_from(Field::from_u64(i)).unwrap(); let staker_address = Address::::try_from(&private_key).unwrap(); @@ -90,26 +79,29 @@ fn bench_bonded_mappings(c: &mut Criterion) { }) .collect::, Value)>>(); - // Insert 100_000 entries into the bonded mapping. - vm.finalize_store().replace_mapping(credits_program_id, bonded_mapping, bonded_map).unwrap(); - - // Get a key to access the bonded mapping with. - let private_key = PrivateKey::try_from(Field::from_u64(0)).unwrap(); + // Get a key that exists within the bonded mapping. + let private_key = PrivateKey::try_from(Field::from_u64(5)).unwrap(); let staker_address = Address::::try_from(&private_key).unwrap(); let key = Plaintext::from(Literal::Address(staker_address)); - // Benchmark get_value_speculative on the bonded mapping at 100_000 entries. - c.bench_function("bonded mapping - get_value_speculative - 100_000 entries", |b| { - b.iter(|| { - let _value = vm.finalize_store().get_value_speculative(credits_program_id, bonded_mapping, &key).unwrap(); - }) - }); - - // Benchmark get_value_confirmed on the bonded mapping at 100_000 entries. - c.bench_function("bonded mapping - get_value_confirmed - 100_000 entries", |b| { - b.iter(|| { - let _value = vm.finalize_store().get_value_confirmed(credits_program_id, bonded_mapping, &key).unwrap(); - }) + // Insert increasing numbers of entries into the bonded mapping and bench get_value_speculative and get_value_confirmed at each interval. + BONDED_INTERVALS.iter().for_each(|num_entries| { + let entries = bonded_map.iter().take(*num_entries).cloned().collect::>(); + vm.finalize_store().replace_mapping(credits_program_id, bonded_mapping, entries).unwrap(); + + // Benchmark get_value_speculative on the bonded mapping. + c.bench_function(&format!("bonded mapping - get_value_speculative - {num_entries} entries"), |b| { + b.iter(|| { + vm.finalize_store().get_value_speculative(credits_program_id, bonded_mapping, &key).unwrap(); + }) + }); + + // Benchmark get_value_confirmed on the bonded mapping. + c.bench_function(&format!("bonded mapping - get_value_confirmed - {num_entries} entries"), |b| { + b.iter(|| { + vm.finalize_store().get_value_confirmed(credits_program_id, bonded_mapping, &key).unwrap(); + }) + }); }); } From 2656dfa890fade401456f858c8a1f6c61e20388f Mon Sep 17 00:00:00 2001 From: Michael Turner Date: Fri, 19 Apr 2024 09:56:02 -0400 Subject: [PATCH 3/3] Move bonded benchmark to ledger crate --- ledger/Cargo.toml | 5 +++++ .../bond_mapping.rs => ledger/benches/bonded_mapping.rs | 7 ++----- synthesizer/Cargo.toml | 5 ----- 3 files changed, 7 insertions(+), 10 deletions(-) rename synthesizer/benches/bond_mapping.rs => ledger/benches/bonded_mapping.rs (95%) diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index be34ffd2b4..e75f892a86 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -21,6 +21,11 @@ name = "block" path = "benches/block.rs" harness = false +[[bench]] +name = "bonded_mapping" +path = "benches/bonded_mapping.rs" +harness = false + [[bench]] name = "transaction" path = "benches/transaction.rs" diff --git a/synthesizer/benches/bond_mapping.rs b/ledger/benches/bonded_mapping.rs similarity index 95% rename from synthesizer/benches/bond_mapping.rs rename to ledger/benches/bonded_mapping.rs index fa877ee933..94d9e7b967 100644 --- a/synthesizer/benches/bond_mapping.rs +++ b/ledger/benches/bonded_mapping.rs @@ -27,13 +27,10 @@ use ledger_store::helpers::memory::ConsensusMemory; #[cfg(feature = "rocks")] use ledger_store::helpers::rocksdb::ConsensusDB; use ledger_store::ConsensusStore; -use snarkvm_synthesizer::VM; -use utilities::cfg_into_iter; +use synthesizer::VM; use criterion::Criterion; use indexmap::indexmap; -#[cfg(not(feature = "serial"))] -use rayon::iter::{IntoParallelIterator, ParallelIterator}; use std::{str::FromStr, time::Duration}; pub type CurrentNetwork = MainnetV0; @@ -61,7 +58,7 @@ fn bench_bonded_mappings(c: &mut Criterion) { Address::from_str("aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px").unwrap(); // Generate 100_000 bonded mapping entries. - let bonded_map = cfg_into_iter!((0..(MAX_DELEGATORS as u64))) + let bonded_map = (0..(MAX_DELEGATORS as u64)) .map(|i| { // Generate a staker address. let private_key = PrivateKey::try_from(Field::from_u64(i)).unwrap(); diff --git a/synthesizer/Cargo.toml b/synthesizer/Cargo.toml index c53344aa52..13167e27de 100644 --- a/synthesizer/Cargo.toml +++ b/synthesizer/Cargo.toml @@ -60,11 +60,6 @@ wasm = [ "synthesizer-snark/wasm" ] -[[bench]] -name = "bond_mapping" -path = "benches/bond_mapping.rs" -harness = false - [[bench]] name = "kary_merkle_tree" path = "benches/kary_merkle_tree.rs"