-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: performance improvement and benchmark (#5)
* add benchmark * clippy * wrap arc * fix
- Loading branch information
Showing
10 changed files
with
667 additions
and
50 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#![allow(missing_docs)] | ||
use criterion::{criterion_group, criterion_main, Criterion}; | ||
use poseidon_bn254::{hash_with_domain, Fr, PrimeField}; | ||
use rand::prelude::*; | ||
use zktrie::HashField; | ||
use zktrie_ng::trie::NodeType; | ||
use zktrie_ng::{ | ||
hash::{poseidon::Poseidon, HashScheme}, | ||
trie::Node, | ||
}; | ||
use zktrie_rust::hash::AsHash; | ||
|
||
type OldNode = zktrie_rust::types::Node<AsHash<HashField>>; | ||
|
||
fn bench_parse_node_inner(c: &mut Criterion, name: &str, node_bytes: Vec<u8>) { | ||
let mut group = c.benchmark_group(name); | ||
group.bench_with_input("zktrie-ng", &node_bytes, |b, node_bytes| { | ||
b.iter(|| { | ||
let node = Node::<Poseidon>::try_from(node_bytes.as_slice()).unwrap(); | ||
*node.get_or_calculate_node_hash().unwrap() | ||
}); | ||
}); | ||
group.bench_with_input("zktrie", &node_bytes, |b, node_bytes| { | ||
b.iter(|| { | ||
OldNode::new_node_from_bytes(node_bytes) | ||
.unwrap() | ||
.calc_node_hash() | ||
.unwrap() | ||
.node_hash() | ||
.unwrap() | ||
}); | ||
}); | ||
group.finish(); | ||
} | ||
|
||
fn bench_parse_node(c: &mut Criterion) { | ||
let mut rng = SmallRng::seed_from_u64(42); | ||
|
||
let account_leaf = { | ||
let key: [u8; 20] = rng.gen(); | ||
let values: [[u8; 32]; 5] = rng.gen(); | ||
Node::<Poseidon>::new_leaf( | ||
Poseidon::hash_bytes(&key).unwrap(), | ||
values.to_vec(), | ||
0b11111, | ||
None, | ||
) | ||
.unwrap() | ||
}; | ||
bench_parse_node_inner(c, "Parse Account Node", account_leaf.canonical_value(false)); | ||
|
||
let storage_leaf = { | ||
let key: [u8; 32] = rng.gen(); | ||
let values: [[u8; 32]; 1] = rng.gen(); | ||
Node::<Poseidon>::new_leaf( | ||
Poseidon::hash_bytes(&key).unwrap(), | ||
values.to_vec(), | ||
0b1, | ||
None, | ||
) | ||
.unwrap() | ||
}; | ||
|
||
bench_parse_node_inner(c, "Parse Storage Node", storage_leaf.canonical_value(false)); | ||
|
||
let branch_node = Node::<Poseidon>::new_branch( | ||
NodeType::BranchLTRT, | ||
*account_leaf.get_or_calculate_node_hash().unwrap(), | ||
*storage_leaf.get_or_calculate_node_hash().unwrap(), | ||
); | ||
|
||
bench_parse_node_inner(c, "Parse Branch Node", branch_node.canonical_value(false)); | ||
} | ||
|
||
fn poseidon_hash_scheme(a: &[u8; 32], b: &[u8; 32], domain: &[u8; 32]) -> Option<[u8; 32]> { | ||
let a = Fr::from_repr_vartime(*a)?; | ||
let b = Fr::from_repr_vartime(*b)?; | ||
let domain = Fr::from_repr_vartime(*domain)?; | ||
Some(hash_with_domain(&[a, b], domain).to_repr()) | ||
} | ||
|
||
fn criterion_benchmark(c: &mut Criterion) { | ||
zktrie::init_hash_scheme_simple(poseidon_hash_scheme); | ||
bench_parse_node(c); | ||
} | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#![allow(missing_docs)] | ||
|
||
use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; | ||
use poseidon_bn254::{hash_with_domain, Fr, PrimeField}; | ||
use rand::prelude::*; | ||
use std::hint::black_box; | ||
use zktrie::HashField; | ||
use zktrie_ng::db::HashMapDb; | ||
use zktrie_ng::hash::key_hasher::NoCacheHasher; | ||
use zktrie_ng::{ | ||
hash::{poseidon::Poseidon, HashScheme}, | ||
trie::ZkTrie, | ||
}; | ||
use zktrie_rust::{db::SimpleDb, hash::AsHash, types::TrieHashScheme}; | ||
|
||
type NodeOld = zktrie_rust::types::Node<AsHash<HashField>>; | ||
type TrieOld = | ||
zktrie_rust::raw::ZkTrieImpl<AsHash<HashField>, SimpleDb, { Poseidon::TRIE_MAX_LEVELS }>; | ||
|
||
fn bench_trie_update(c: &mut Criterion) { | ||
let mut rng = SmallRng::seed_from_u64(42); | ||
let mut group = c.benchmark_group("Trie Update"); | ||
|
||
let k: [u8; 20] = rng.gen(); | ||
let values: [[u8; 32]; 5] = rng.gen(); | ||
let values = values.to_vec(); | ||
|
||
group.bench_with_input("zktrie-ng", &(k, values.clone()), |b, (k, values)| { | ||
b.iter_batched( | ||
|| { | ||
let trie = ZkTrie::default(); | ||
(trie, k, values.clone()) | ||
}, | ||
|(mut trie, k, values)| { | ||
trie.raw_update(k, values, black_box(0b11111)).unwrap(); | ||
}, | ||
BatchSize::SmallInput, | ||
); | ||
}); | ||
|
||
group.bench_with_input("zktrie", &(k, values), |b, (k, values)| { | ||
b.iter_batched( | ||
|| { | ||
let trie = TrieOld::new_zktrie_impl(SimpleDb::new()).unwrap(); | ||
(trie, k, values.clone()) | ||
}, | ||
|(mut trie, k, values)| { | ||
let key = NodeOld::hash_bytes(k).unwrap(); | ||
trie.try_update(&key, black_box(0b11111), values).unwrap(); | ||
}, | ||
BatchSize::SmallInput, | ||
); | ||
}); | ||
} | ||
|
||
fn bench_trie_operation(c: &mut Criterion) { | ||
let mut rng = SmallRng::seed_from_u64(42); | ||
|
||
let mut trie = ZkTrie::default(); | ||
let mut trie_old = TrieOld::new_zktrie_impl(SimpleDb::new()).unwrap(); | ||
|
||
let mut keys = vec![]; | ||
|
||
for _ in 0..100 { | ||
let k: [u8; 20] = rng.gen(); | ||
let values: [[u8; 32]; 5] = rng.gen(); | ||
let values = values.to_vec(); | ||
|
||
trie.raw_update(k, values.clone(), 0b11111).unwrap(); | ||
let key = NodeOld::hash_bytes(&k).unwrap(); | ||
trie_old.try_update(&key, 0b11111, values).unwrap(); | ||
keys.push((Poseidon::hash_bytes(&k).unwrap(), key)); | ||
} | ||
|
||
trie.commit().unwrap(); | ||
trie_old.prepare_root().unwrap(); | ||
trie_old.commit().unwrap(); | ||
|
||
let mut group = c.benchmark_group("Trie Get"); | ||
keys.shuffle(&mut rng); | ||
group.bench_with_input("zktrie-ng", &(&trie, &keys[..10]), |b, (trie, keys)| { | ||
b.iter(|| { | ||
keys.iter() | ||
.map(|(key, _)| trie.get_node_by_key(key).unwrap()) | ||
.collect::<Vec<_>>() | ||
}); | ||
}); | ||
group.bench_with_input("zktrie", &(&trie_old, &keys[..10]), |b, (trie, keys)| { | ||
b.iter(|| { | ||
keys.iter() | ||
.map(|(_, key)| trie.try_get(key).unwrap()) | ||
.collect::<Vec<_>>() | ||
}); | ||
}); | ||
group.finish(); | ||
|
||
let mut group = c.benchmark_group("Trie Delete"); | ||
keys.shuffle(&mut rng); | ||
group.bench_with_input("zktrie-ng", &(&trie, &keys[..10]), |b, (trie, keys)| { | ||
b.iter_batched( | ||
|| { | ||
let root = *trie.root().unwrap_ref(); | ||
let db = HashMapDb::from_map(false, trie.db().inner().clone()); | ||
let trie = ZkTrie::<Poseidon>::new_with_root(db, NoCacheHasher, root).unwrap(); | ||
(trie, keys) | ||
}, | ||
|(mut trie, keys)| { | ||
for (key, _) in keys.iter() { | ||
trie.delete_by_node_key(*key).unwrap(); | ||
} | ||
}, | ||
BatchSize::SmallInput, | ||
) | ||
}); | ||
group.bench_with_input("zktrie", &(&trie_old, &keys[..10]), |b, (trie, keys)| { | ||
b.iter_batched( | ||
|| { | ||
let root = trie.root(); | ||
let db = trie.get_db().clone(); | ||
let trie = TrieOld::new_zktrie_impl_with_root(db, root).unwrap(); | ||
(trie, keys) | ||
}, | ||
|(mut trie, keys)| { | ||
for (_, key) in keys.iter() { | ||
trie.try_delete(key).unwrap(); | ||
} | ||
}, | ||
BatchSize::SmallInput, | ||
) | ||
}); | ||
group.finish(); | ||
} | ||
|
||
fn poseidon_hash_scheme(a: &[u8; 32], b: &[u8; 32], domain: &[u8; 32]) -> Option<[u8; 32]> { | ||
let a = Fr::from_repr_vartime(*a)?; | ||
let b = Fr::from_repr_vartime(*b)?; | ||
let domain = Fr::from_repr_vartime(*domain)?; | ||
Some(hash_with_domain(&[a, b], domain).to_repr()) | ||
} | ||
|
||
fn criterion_benchmark(c: &mut Criterion) { | ||
zktrie::init_hash_scheme_simple(poseidon_hash_scheme); | ||
bench_trie_update(c); | ||
bench_trie_operation(c); | ||
} | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.