diff --git a/Cargo.toml b/Cargo.toml index df73a393782fb60769b8eb6d8295ef546fb7b6fb..6e71ae55b967076c58a5ef9da9020af57fe4a4d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,10 +51,6 @@ ark-secq256k1 = "0.4.0" ark-vesta = "0.4.0" criterion = "0.3" -[[bench]] -name = "recoding" -harness = false - [[example]] name = "bench_commit" path = "examples/benches/commit.rs" @@ -78,3 +74,7 @@ path = "examples/benches/setup.rs" [[example]] name = "bench_linalg" path = "examples/benches/linalg.rs" + +[[example]] +name = "bench_recoding" +path = "examples/benches/recoding.rs" diff --git a/README.md b/README.md index e1d9558b0c0bb861420bdeca128044b61a939ac5..cd4f411ccd8a417b3a65d6a30642d6a91139a682 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,6 @@ tests for the binary application can also be run with ```bash nu tests/cli.nu ``` + +## the benchmarks +see [the `README`](examples/benches/README.md) diff --git a/benches/recoding.rs b/benches/recoding.rs deleted file mode 100644 index f623f6c17cf564b521ab8cd33d7c24828ede9db1..0000000000000000000000000000000000000000 --- a/benches/recoding.rs +++ /dev/null @@ -1,77 +0,0 @@ -// see `benches/README.md` -use std::time::Duration; - -use ark_ff::PrimeField; -use ark_std::rand::Rng; - -use criterion::{criterion_group, criterion_main, Criterion}; - -use komodo::{ - fec::{recode_with_coeffs, Shard}, - field, -}; - -fn to_curve<F: PrimeField>(n: u128) -> F { - F::from_le_bytes_mod_order(&n.to_le_bytes()) -} - -fn create_fake_shard<F: PrimeField>(nb_bytes: usize, k: usize) -> Shard<F> { - let mut rng = rand::thread_rng(); - let bytes: Vec<u8> = (0..nb_bytes).map(|_| rng.gen::<u8>()).collect(); - - let linear_combination: Vec<F> = (0..k).map(|_| to_curve::<F>(rng.gen::<u128>())).collect(); - - Shard { - k: k as u32, - linear_combination, - hash: vec![], - data: field::split_data_into_field_elements::<F>(&bytes, 1), - size: 0, - } -} - -fn bench_template<F: PrimeField>( - c: &mut Criterion, - nb_bytes: usize, - k: usize, - nb_shards: usize, - curve: &str, -) { - let shards: Vec<Shard<F>> = (0..nb_shards) - .map(|_| create_fake_shard(nb_bytes, k)) - .collect(); - - let mut rng = rand::thread_rng(); - let coeffs: Vec<F> = (0..nb_shards) - .map(|_| to_curve::<F>(rng.gen::<u128>())) - .collect(); - - c.bench_function( - &format!( - "recoding {} bytes and {} shards with k = {} on {}", - nb_bytes, nb_shards, k, curve - ), - |b| b.iter(|| recode_with_coeffs(&shards, &coeffs)), - ); -} - -fn criterion_benchmark(c: &mut Criterion) { - for nb_bytes in [1, 1_024, 1_024 * 1_024] { - for nb_shards in [2, 4, 8, 16] { - for k in [2, 4, 8, 16] { - bench_template::<ark_bls12_381::Fr>(c, nb_bytes, k, nb_shards, "BLS-12-381"); - bench_template::<ark_bn254::Fr>(c, nb_bytes, k, nb_shards, "BN-254"); - bench_template::<ark_pallas::Fr>(c, nb_bytes, k, nb_shards, "PALLAS"); - } - } - } -} - -criterion_group!( - name = benches; - config = Criterion::default() - .warm_up_time(Duration::from_secs_f32(0.5)) - .sample_size(10); - targets = criterion_benchmark -); -criterion_main!(benches); diff --git a/benches/README.md b/examples/benches/README.md similarity index 65% rename from benches/README.md rename to examples/benches/README.md index 4f04dc131270ba8ac2a25bfe067e8c26b92c1a02..b123bab220291c6e782ce83d81622959b87d3c54 100644 --- a/benches/README.md +++ b/examples/benches/README.md @@ -1,5 +1,6 @@ ```nushell use scripts/math.nu * +use scripts/formats.nu * ``` ## atomic operations @@ -62,9 +63,8 @@ for graph in [ ( $linalg | where op == $graph.op - | rename --column { n: "x", name: "curve", mean: "measurement", stddev: "error" } - | group-by curve --to-table - | update items { reject curve } + | rename --column { n: "x", mean: "measurement", stddev: "error" } + | group-by name --to-table | to json ) ] @@ -86,15 +86,14 @@ python scripts/plot/plot.py ...[ | ns-to-ms $.times | compute-stats $.times | insert degree { get label | parse "degree {d}" | into record | get d | into int} - | insert curve {|it| if ($it.name | str starts-with "ARK") { + | update name {|it| if ($it.name | str starts-with "ARK") { let c = $it.name | parse "ARK setup on {curve}" | into record | get curve $"($c)-ark" } else { $it.name | parse "setup on {curve}" | into record | get curve }} | rename --column { degree: "x", mean: "measurement", stddev: "error" } - | group-by curve --to-table - | update items { reject curve } + | group-by name --to-table | to json ) ] @@ -114,11 +113,52 @@ python scripts/plot/plot.py ...[ open commit.ndjson | ns-to-ms $.times | compute-stats $.times - | update label { parse "degree {d}" | into record | get d | into int } - | rename --column { label: "x", name: "curve", mean: "measurement", stddev: "error" } - | group-by curve --to-table - | update items { reject curve } + | insert degree { get label | parse "degree {d}" | into record | get d | into int } + | rename --column { degree: "x", mean: "measurement", stddev: "error" } + | group-by name --to-table | to json ) ] ``` + +## end-to-end benchmarks +### recoding +```nushell +cargo run --example bench_recoding -- ...[ + --nb-measurements 10 + ...[1, 1_024, (1_024 * 1_024)] + --shards ...[2, 4, 8, 16] + --ks ...[2, 4, 8, 16] +] | from ndnuon | to ndjson out> recoding.ndjson +``` +```nushell +python scripts/plot/plot.py --title "recoding with k = 4" ( + open recoding.ndjson + | ns-to-ms $.times + | compute-stats $.times + | update label { from nuon } + | flatten --all label + | insert case { $"($in.name) / ($in.shards)" } + | where k == 4 # $k$ has a negligible influence on _recoding_ + | rename --column { bytes: "x", mean: "measurement", stddev: "error" } + | group-by case --to-table + | insert style {|it| + let g = $it.group | parse "{c} / {s}" | into record | into int s + let c = match $g.c { + "BLS-12-381" => "blue" + "BN-254" => "orange" + "PALLAS" => "green" + _ => "gray" + } + let t = match $g.s { + 2 => "dotted" + 4 => "dashdot" + 8 => "dashed" + 16 => "solid" + _ => { color: "loosely dotted" } + } + { color: $c, line: { type: $t } } + } + | to json +) +``` diff --git a/examples/benches/recoding.rs b/examples/benches/recoding.rs new file mode 100644 index 0000000000000000000000000000000000000000..610330ce41fb2d613b24727c7b2d5e763bc1ff47 --- /dev/null +++ b/examples/benches/recoding.rs @@ -0,0 +1,83 @@ +// see `benches/README.md` +use ark_ff::PrimeField; +use ark_std::rand::Rng; + +use clap::{arg, command, Parser}; +use komodo::{ + fec::{recode_with_coeffs, Shard}, + field, +}; +use plnk::Bencher; + +fn to_curve<F: PrimeField>(n: u128) -> F { + F::from_le_bytes_mod_order(&n.to_le_bytes()) +} + +fn create_fake_shard<F: PrimeField>(nb_bytes: usize, k: usize) -> Shard<F> { + let mut rng = rand::thread_rng(); + let bytes: Vec<u8> = (0..nb_bytes).map(|_| rng.gen::<u8>()).collect(); + + let linear_combination: Vec<F> = (0..k).map(|_| to_curve::<F>(rng.gen::<u128>())).collect(); + + Shard { + k: k as u32, + linear_combination, + hash: vec![], + data: field::split_data_into_field_elements::<F>(&bytes, 1), + size: 0, + } +} + +fn bench_template<F: PrimeField>(b: &Bencher, nb_bytes: usize, k: usize, nb_shards: usize) { + let shards: Vec<Shard<F>> = (0..nb_shards) + .map(|_| create_fake_shard(nb_bytes, k)) + .collect(); + + let mut rng = rand::thread_rng(); + let coeffs: Vec<F> = (0..nb_shards) + .map(|_| to_curve::<F>(rng.gen::<u128>())) + .collect(); + + plnk::bench( + b, + &format!( + r#"{{"bytes": {}, "shards": {}, "k": {}}}"#, + nb_bytes, nb_shards, k + ), + || plnk::timeit(|| recode_with_coeffs(&shards, &coeffs)), + ); +} + +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct Cli { + #[arg(num_args = 1.., value_delimiter = ' ')] + bytes: Vec<usize>, + + #[arg(short, long, num_args = 1.., value_delimiter = ' ')] + shards: Vec<usize>, + + #[arg(short, long, num_args = 1.., value_delimiter = ' ')] + ks: Vec<usize>, + + /// the number of measurements to repeat each case, larger values will reduce the variance of + /// the measurements + #[arg(short, long)] + nb_measurements: usize, +} + +fn main() { + let cli = Cli::parse(); + + let bencher = plnk::Bencher::new(cli.nb_measurements); + + for b in cli.bytes { + for s in &cli.shards { + for k in &cli.ks { + bench_template::<ark_bls12_381::Fr>(&bencher.with_name("BLS-12-381"), b, *k, *s); + bench_template::<ark_bn254::Fr>(&bencher.with_name("BN-254"), b, *k, *s); + bench_template::<ark_pallas::Fr>(&bencher.with_name("PALLAS"), b, *k, *s); + } + } + } +} diff --git a/scripts/formats.nu b/scripts/formats.nu new file mode 100644 index 0000000000000000000000000000000000000000..3b07548c071356aff281c62cec830c3e7b6600ef --- /dev/null +++ b/scripts/formats.nu @@ -0,0 +1,15 @@ +export def "from ndnuon" []: [string -> any] { + lines | each { from nuon } +} + +export def "to ndnuon" []: [any -> string] { + each { to nuon --raw } | to text +} + +export def "from nuonl" []: [string -> any] { + from ndnuon +} + +export def "to nuonl" []: [any -> string] { + to ndnuon +}