diff --git a/Cargo.lock b/Cargo.lock index b0c752ae..d10e648a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,6 +96,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anstream" version = "0.6.4" @@ -177,7 +183,7 @@ dependencies = [ "byteorder", "cfg-if", "color-eyre 0.5.11", - "criterion", + "criterion 0.3.6", "ethers-core 2.0.10 (git+https://github.com/gakonst/ethers-rs)", "fnv", "hex", @@ -808,6 +814,33 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "ciborium" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" + +[[package]] +name = "ciborium-ll" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.4.4" @@ -1155,7 +1188,7 @@ dependencies = [ "atty", "cast", "clap 2.34.0", - "criterion-plot", + "criterion-plot 0.4.5", "csv", "itertools 0.10.5", "lazy_static", @@ -1172,6 +1205,33 @@ dependencies = [ "walkdir", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap 4.4.8", + "criterion-plot 0.5.0", + "futures", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + [[package]] name = "criterion-plot" version = "0.4.5" @@ -1182,6 +1242,16 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -6137,6 +6207,7 @@ dependencies = [ "axum-middleware", "clap 4.4.8", "common", + "criterion 0.5.1", "ethers", "ethers-throttle", "eyre", @@ -6146,6 +6217,7 @@ dependencies = [ "hyper", "metrics", "opentelemetry 0.21.0", + "rand", "reqwest", "ruint", "semaphore", diff --git a/Cargo.toml b/Cargo.toml index b3afeade..6134f35d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ axum = "0.6.20" axum-middleware = { path = "crates/axum-middleware" } clap = { version = "4.4.8", features = ["derive"] } common = { path = "crates/common" } +criterion = { version = "0.5.1", features = ["async", "async_futures"] } ethers = { version = "2.0.10", features = [ "abigen", "ws", @@ -25,6 +26,7 @@ hex = "0.4.3" hyper = { version = "^0.14.27", features = ["server", "tcp", "http1", "http2"] } metrics = "0.21.1" opentelemetry = "0.21.0" +rand = "0.8.5" ruint = "1.10.1" semaphore = { git = "https://github.com/worldcoin/semaphore-rs", branch = "main", features = [ "depth_20", @@ -48,3 +50,9 @@ path = "bin/tree_availability_service.rs" [[bin]] name = "state-bridge-service" path = "bin/state_bridge_service.rs" + +[[bench]] +name = "tree_data" +harness = false + + diff --git a/benches/tree_data.rs b/benches/tree_data.rs new file mode 100644 index 00000000..149389cb --- /dev/null +++ b/benches/tree_data.rs @@ -0,0 +1,123 @@ +use criterion::async_executor::FuturesExecutor; +use criterion::{criterion_group, criterion_main, Criterion}; +use rand::seq::IteratorRandom; +use rand::Rng; +use semaphore::lazy_merkle_tree::Canonical; +use world_tree::tree::tree_data::TreeData; +use world_tree::tree::{Hash, PoseidonTree}; + +pub const TREE_DEPTH: usize = 30; +pub const TREE_HISTORY_SIZE: usize = 24; +pub const NUMBER_OF_IDENTITIES: usize = 100; + +fn generate_random_identity() -> Hash { + let mut rng = rand::thread_rng(); + ruint::Uint::from(rng.gen::()) +} + +fn generate_random_identities(num_identities: usize) -> Vec { + let mut identities = vec![]; + + for _ in 0..(num_identities) { + identities.push(generate_random_identity()); + } + + identities +} + +async fn setup_tree_data() -> TreeData { + let tree = PoseidonTree::::new(TREE_DEPTH, Hash::ZERO); + let tree_data = TreeData::new(tree, TREE_HISTORY_SIZE); + + tree_data + .insert_many_at(0, &generate_random_identities(1 << 10)) + .await; + + tree_data +} + +fn bench_insert_many_at(c: &mut Criterion) { + let mut group = c.benchmark_group("TreeData Insertion"); + + let runtime = tokio::runtime::Runtime::new().unwrap(); + let tree_data = runtime.block_on(setup_tree_data()); + + let identities = generate_random_identities(NUMBER_OF_IDENTITIES); + + group.bench_function("insert_many_at", |b| { + b.to_async(FuturesExecutor) + .iter(|| tree_data.insert_many_at(0, &identities)) + }); +} + +fn bench_delete_many(c: &mut Criterion) { + let mut group = c.benchmark_group("TreeData Deletion"); + + let runtime = tokio::runtime::Runtime::new().unwrap(); + let tree_data = runtime.block_on(setup_tree_data()); + + let delete_indices: Vec = (0..NUMBER_OF_IDENTITIES).collect(); + + group.bench_function("delete_many", |b| { + b.to_async(FuturesExecutor) + .iter(|| tree_data.delete_many(&delete_indices)) + }); +} + +fn bench_get_inclusion_proof_latest_root(c: &mut Criterion) { + let mut group = c.benchmark_group("TreeData Inclusion Proof"); + + let runtime = tokio::runtime::Runtime::new().unwrap(); + let tree_data = runtime.block_on(setup_tree_data()); + + let tree = runtime.block_on(tree_data.tree.read()); + + let random_identity = tree + .leaves() + .choose(&mut rand::thread_rng()) + .expect("Could not get random identity"); + + group.bench_function("get_inclusion_proof at latest root", |b| { + b.to_async(FuturesExecutor) + .iter(|| tree_data.get_inclusion_proof(random_identity, None)) + }); +} + +fn bench_get_inclusion_proof_historical_root(c: &mut Criterion) { + let mut group = + c.benchmark_group("get_inclusion_proof at oldest historical root"); + + let runtime = tokio::runtime::Runtime::new().unwrap(); + + // Insert the target identity + let identity = generate_random_identity(); + let tree_data = runtime.block_on(setup_tree_data()); + runtime.block_on(tree_data.insert_many_at(0, &vec![identity])); + + // Update the tree history + let tree_data = runtime.block_on(async { + for _ in 0..TREE_HISTORY_SIZE { + let identities = generate_random_identities(10); + tree_data.insert_many_at(1, &identities).await; + } + + tree_data + }); + + let tree_history = runtime.block_on(tree_data.tree_history.read()); + let oldest_root = tree_history.back().unwrap().root(); + + group.bench_function("get_inclusion_proof at historical root", |b| { + b.to_async(FuturesExecutor) + .iter(|| tree_data.get_inclusion_proof(identity, Some(oldest_root))) + }); +} + +criterion_group!( + benches, + bench_insert_many_at, + bench_delete_many, + bench_get_inclusion_proof_latest_root, + bench_get_inclusion_proof_historical_root +); +criterion_main!(benches); diff --git a/crates/ethers-throttle/src/lib.rs b/crates/ethers-throttle/src/lib.rs index f67ae0af..8e5f5d9c 100644 --- a/crates/ethers-throttle/src/lib.rs +++ b/crates/ethers-throttle/src/lib.rs @@ -2,7 +2,7 @@ use std::num::NonZeroU32; use std::sync::Arc; use async_trait::async_trait; -use ethers::providers::{JsonRpcClient, ProviderError}; +use ethers::providers::JsonRpcClient; use governor::clock::{QuantaClock, QuantaInstant}; use governor::middleware::NoOpMiddleware; use governor::state::{InMemoryState, NotKeyed};