Skip to content

Commit 1e8382a

Browse files
authored
Collections perf (#24)
* switch to criterion for benchmarking * switch to boxed iterators for collections impls * add debug_asserts feature, enable more tests for nanoserde
1 parent 1a2966e commit 1e8382a

File tree

12 files changed

+306
-158
lines changed

12 files changed

+306
-158
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "structdiff"
3-
version = "0.5.8"
3+
version = "0.5.9"
44
edition = "2021"
55
license = "Apache-2.0 OR MIT"
66
repository = "https://github.com/knickish/structdiff"
@@ -11,14 +11,15 @@ categories = ["compression"]
1111
[dependencies]
1212
nanoserde = { version = "^0.1.32", optional = true }
1313
serde = { version = "^1.0.0", optional = true, features = ["derive"] }
14-
structdiff-derive = { path = "derive", version = "=0.5.8" }
14+
structdiff-derive = { path = "derive", version = "=0.5.9" }
1515

1616
[features]
1717
"default" = []
1818
"nanoserde" = ["dep:nanoserde", "structdiff-derive/nanoserde"]
1919
"serde" = ["dep:serde", "structdiff-derive/serde"]
2020
"debug_diffs" = ["structdiff-derive/debug_diffs"]
2121
"generated_setters" = ["structdiff-derive/generated_setters"]
22+
"debug_asserts" = []
2223

2324
[dev-dependencies]
2425
bincode = "1.3.3"

benchmarks/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
/target
2-
Cargo.lock
2+
Cargo.lock
3+
flamegraph.svg
4+
perf.data*

benchmarks/Cargo.toml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,27 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9+
assert_unordered = "0.3.5"
910
structdiff = { path = "..", features = ["serde"] }
1011
nanorand = { version = "0.7.0" }
11-
diff-struct = { version = "0.5.1" }
12+
diff-struct = { version = "0.5.1", optional = true}
1213
serde = { version = "^1.0.0", features = ["derive"] }
13-
serde-diff = { version = "0.4.1" }
14+
serde-diff = { version = "0.4.1", optional = true}
1415
bincode = { version = "1.3.3" }
16+
criterion = "0.5.1"
17+
18+
[features]
19+
compare = ["dep:serde-diff", "dep:diff-struct"]
1520

1621
[profile.bench]
1722
lto = "fat"
18-
opt-level = 3
23+
opt-level = 3
24+
debug = true
25+
26+
[[bench]]
27+
name = "basic"
28+
harness = false
29+
30+
[[bench]]
31+
name = "large"
32+
harness = false

benchmarks/benches/basic.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#![cfg(test)]
2+
3+
extern crate structdiff_benchmarks;
4+
5+
use std::time::Duration;
6+
7+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
8+
use nanorand::WyRand;
9+
use structdiff::StructDiff;
10+
use structdiff_benchmarks::TestBench;
11+
const SAMPLE_SIZE: usize = 1000;
12+
const MEASUREMENT_TIME: Duration = Duration::from_secs(25);
13+
const SEED: u64 = 42;
14+
15+
#[cfg(feature = "compare")]
16+
criterion_group!(
17+
benches,
18+
bench_basic,
19+
diff_struct_bench::bench_basic,
20+
serde_diff_bench::bench_basic
21+
);
22+
#[cfg(not(feature = "compare"))]
23+
criterion_group!(benches, bench_basic);
24+
25+
criterion_main!(benches);
26+
27+
fn bench_basic(c: &mut Criterion) {
28+
const GROUP_NAME: &str = "bench_basic";
29+
let mut rng = WyRand::new_seed(SEED);
30+
let mut first = black_box(TestBench::generate_random(&mut rng));
31+
let second = black_box(TestBench::generate_random(&mut rng));
32+
let mut group = c.benchmark_group(GROUP_NAME);
33+
group
34+
.sample_size(SAMPLE_SIZE)
35+
.measurement_time(MEASUREMENT_TIME);
36+
group.bench_function(GROUP_NAME, |b| {
37+
b.iter(|| {
38+
let diff = black_box(StructDiff::diff(&first, &second));
39+
black_box(first.apply_mut(diff));
40+
})
41+
});
42+
group.finish();
43+
first.assert_eq(second);
44+
}
45+
46+
#[cfg(feature = "compare")]
47+
mod diff_struct_bench {
48+
use super::{black_box, Criterion, TestBench, WyRand, MEASUREMENT_TIME, SAMPLE_SIZE, SEED};
49+
use diff::Diff;
50+
51+
pub(super) fn bench_basic(c: &mut Criterion) {
52+
const GROUP_NAME: &str = "diff_struct_bench_basic";
53+
let mut rng = WyRand::new_seed(SEED);
54+
let mut first = black_box(TestBench::generate_random(&mut rng));
55+
let second = black_box(TestBench::generate_random(&mut rng));
56+
let mut group = c.benchmark_group(GROUP_NAME);
57+
group
58+
.sample_size(SAMPLE_SIZE)
59+
.measurement_time(MEASUREMENT_TIME);
60+
group.bench_function(GROUP_NAME, |b| {
61+
b.iter(|| {
62+
let diff = black_box(Diff::diff(&first, &second));
63+
black_box(Diff::apply(&mut first, &diff))
64+
})
65+
});
66+
group.finish();
67+
assert_eq!(first.b, second.b);
68+
}
69+
}
70+
71+
#[cfg(feature = "compare")]
72+
mod serde_diff_bench {
73+
use super::{black_box, Criterion, TestBench, WyRand, MEASUREMENT_TIME, SAMPLE_SIZE, SEED};
74+
use bincode::Options;
75+
76+
pub(super) fn bench_basic(c: &mut Criterion) {
77+
const GROUP_NAME: &str = "serde_diff_bench_basic";
78+
let mut rng = WyRand::new_seed(SEED);
79+
let mut first = black_box(TestBench::generate_random(&mut rng));
80+
let second = black_box(TestBench::generate_random(&mut rng));
81+
let options = bincode::DefaultOptions::new()
82+
.with_fixint_encoding()
83+
.allow_trailing_bytes();
84+
let mut group = c.benchmark_group(GROUP_NAME);
85+
group
86+
.sample_size(SAMPLE_SIZE)
87+
.measurement_time(MEASUREMENT_TIME);
88+
group.bench_function(GROUP_NAME, |b| {
89+
b.iter(|| {
90+
let mut diff = black_box(
91+
options
92+
.serialize(&serde_diff::Diff::serializable(&first, &second))
93+
.unwrap(),
94+
);
95+
let mut deserializer =
96+
black_box(bincode::Deserializer::from_slice(&mut diff[..], options));
97+
serde_diff::Apply::apply(&mut deserializer, &mut first).unwrap();
98+
})
99+
});
100+
group.finish();
101+
assert_eq!(first.b, second.b);
102+
}
103+
}

benchmarks/benches/large.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#![cfg(test)]
2+
3+
extern crate structdiff_benchmarks;
4+
5+
use std::time::Duration;
6+
7+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
8+
use nanorand::WyRand;
9+
use structdiff::StructDiff;
10+
use structdiff_benchmarks::TestBench;
11+
const SAMPLE_SIZE: usize = 500;
12+
const MEASUREMENT_TIME: Duration = Duration::from_secs(40);
13+
const SEED: u64 = 42;
14+
15+
#[cfg(feature = "compare")]
16+
criterion_group!(
17+
benches,
18+
bench_large,
19+
diff_struct_bench::bench_large,
20+
serde_diff_bench::bench_large
21+
);
22+
#[cfg(not(feature = "compare"))]
23+
criterion_group!(benches, bench_large);
24+
25+
criterion_main!(benches);
26+
27+
fn bench_large(c: &mut Criterion) {
28+
const GROUP_NAME: &str = "bench_large";
29+
let mut rng = WyRand::new_seed(SEED);
30+
let mut first = black_box(TestBench::generate_random_large(&mut rng));
31+
let second = black_box(TestBench::generate_random_large(&mut rng));
32+
let mut group = c.benchmark_group(GROUP_NAME);
33+
group
34+
.sample_size(SAMPLE_SIZE)
35+
.measurement_time(MEASUREMENT_TIME);
36+
group.bench_function(GROUP_NAME, |b| {
37+
b.iter(|| {
38+
let diff = black_box(StructDiff::diff(&first, &second));
39+
black_box(first.apply_mut(diff));
40+
})
41+
});
42+
group.finish();
43+
assert_eq!(first.b, second.b);
44+
}
45+
46+
#[cfg(feature = "compare")]
47+
mod diff_struct_bench {
48+
use super::{black_box, Criterion, TestBench, WyRand, MEASUREMENT_TIME, SAMPLE_SIZE, SEED};
49+
use diff::Diff;
50+
51+
pub(super) fn bench_large(c: &mut Criterion) {
52+
const GROUP_NAME: &str = "diff_struct_bench_large";
53+
let mut rng = WyRand::new_seed(SEED);
54+
let mut first = black_box(TestBench::generate_random_large(&mut rng));
55+
let second = black_box(TestBench::generate_random_large(&mut rng));
56+
let mut group = c.benchmark_group(GROUP_NAME);
57+
group
58+
.sample_size(SAMPLE_SIZE)
59+
.measurement_time(MEASUREMENT_TIME);
60+
group.bench_function(GROUP_NAME, |b| {
61+
b.iter(|| {
62+
let diff = black_box(Diff::diff(&first, &second));
63+
black_box(Diff::apply(&mut first, &diff))
64+
})
65+
});
66+
group.finish();
67+
assert_eq!(first.b, second.b);
68+
}
69+
}
70+
71+
#[cfg(feature = "compare")]
72+
mod serde_diff_bench {
73+
use super::{black_box, Criterion, TestBench, WyRand, MEASUREMENT_TIME, SAMPLE_SIZE, SEED};
74+
use bincode::Options;
75+
76+
pub(super) fn bench_large(c: &mut Criterion) {
77+
const GROUP_NAME: &str = "serde_diff_bench_large";
78+
let mut rng = WyRand::new_seed(SEED);
79+
let mut first = black_box(TestBench::generate_random_large(&mut rng));
80+
let second = black_box(TestBench::generate_random_large(&mut rng));
81+
let options = bincode::DefaultOptions::new()
82+
.with_fixint_encoding()
83+
.allow_trailing_bytes();
84+
let mut group = c.benchmark_group(GROUP_NAME);
85+
group
86+
.sample_size(SAMPLE_SIZE)
87+
.measurement_time(MEASUREMENT_TIME);
88+
group.bench_function(GROUP_NAME, |b| {
89+
b.iter(|| {
90+
let mut diff = black_box(
91+
options
92+
.serialize(&serde_diff::Diff::serializable(&first, &second))
93+
.unwrap(),
94+
);
95+
let mut deserializer = bincode::Deserializer::from_slice(&mut diff[..], options);
96+
serde_diff::Apply::apply(&mut deserializer, &mut first).unwrap();
97+
})
98+
});
99+
group.finish();
100+
assert_eq!(first.b, second.b);
101+
}
102+
}

0 commit comments

Comments
 (0)