Implement minimal benchmarking of dependency tracking

This commit is contained in:
2021-07-10 22:10:16 +02:00
parent 79ed599a2f
commit 308af218e1
4 changed files with 93 additions and 3 deletions

View File

@@ -30,7 +30,8 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: build
args: --all-features
# --all-targets ensures that we also build the benchmarks and tests already.
args: --all-features --all-targets
- uses: actions-rs/cargo@v1
with:

View File

@@ -7,13 +7,15 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Added generic support for wrapping mutexes that implement the traits provided by the
- Generic support for wrapping mutexes that implement the traits provided by the
[`lock_api`][lock_api] crate. This can be used for creating support for other mutex providers that
implement it.
- Added support for [`parking_lot`][parking_lot] mutexes. Support includes type aliases for all
- Support for [`parking_lot`][parking_lot] mutexes. Support includes type aliases for all
provided mutex types as well as a dedicated `Once` wrapper.
- Simple benchmark to track the rough performance penalty incurred by dependency tracking.
## [0.1.2] - 2021-05-27
### Added

View File

@@ -17,8 +17,13 @@ lock_api = { version = "0.4", optional = true }
parking_lot = { version = "0.11", optional = true }
[dev-dependencies]
criterion = "0.3"
rand = "0.8"
[[bench]]
name = "mutex"
harness = false
[features]
# Feature names do not match crate names pending namespaced features.
lockapi = ["lock_api"]

82
benches/mutex.rs Normal file
View File

@@ -0,0 +1,82 @@
use std::sync::Arc;
use std::sync::Mutex;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::BenchmarkId;
use criterion::Criterion;
use criterion::Throughput;
use rand::prelude::*;
use tracing_mutex::stdsync::TracingMutex;
const SAMPLE_SIZES: [usize; 5] = [10, 30, 100, 300, 1000];
/// Reproducibly generate random combinations a, b where the index(a) < index(b)
///
/// All combinations are generated
fn generate_combinations<T>(options: &[Arc<T>]) -> Vec<(Arc<T>, Arc<T>)> {
let mut combinations = Vec::new();
for (i, first) in options.iter().enumerate() {
for second in options.iter().skip(i + 1) {
combinations.push((Arc::clone(first), Arc::clone(second)));
}
}
let mut rng = StdRng::seed_from_u64(42);
combinations.shuffle(&mut rng);
combinations
}
/// Take two arbitrary mutexes, lock the first, lock the second while holding the first.
fn benchmark_baseline(c: &mut Criterion) {
let mut group = c.benchmark_group("baseline");
for nodes in SAMPLE_SIZES {
group.throughput(Throughput::Elements((nodes * (nodes - 1) / 2) as u64));
group.bench_with_input(BenchmarkId::from_parameter(nodes), &nodes, |b, &s| {
b.iter_batched(
|| {
let mutexes: Vec<_> = (0..s).map(|_| Arc::new(Mutex::new(()))).collect();
generate_combinations(&mutexes)
},
|combinations| {
for (first, second) in combinations {
let _first = first.lock();
let _second = second.lock();
}
},
criterion::BatchSize::SmallInput,
)
});
}
}
/// Same as [`benchmark_baseline`] but now while tracking dependencies.
fn benchmark_tracing_mutex(c: &mut Criterion) {
let mut group = c.benchmark_group("tracing_mutex");
for nodes in SAMPLE_SIZES {
group.throughput(Throughput::Elements((nodes * (nodes - 1) / 2) as u64));
group.bench_with_input(BenchmarkId::from_parameter(nodes), &nodes, |b, &s| {
b.iter_batched(
|| {
let mutexes: Vec<_> = (0..s).map(|_| Arc::new(TracingMutex::new(()))).collect();
generate_combinations(&mutexes)
},
|combinations| {
for (first, second) in combinations {
let _first = first.lock();
let _second = second.lock();
}
},
criterion::BatchSize::SmallInput,
)
});
}
}
criterion_group!(benches, benchmark_baseline, benchmark_tracing_mutex);
criterion_main!(benches);