Skip to content

Commit

Permalink
Benchmarks, bumped version (#147)
Browse files Browse the repository at this point in the history
* Some simple mutex benchmarks

* Bumped version

* Remove stable feature

* Make MSRV only check core crate
  • Loading branch information
zesterer committed Mar 28, 2023
1 parent d801e7c commit 907a550
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- run: rustup target add thumbv7m-none-eabi
- name: Ensure we don't depend on libstd
run: cargo hack build --target thumbv7m-none-eabi --no-dev-deps --no-default-features

msrv:
runs-on: ubuntu-latest
strategy:
Expand All @@ -44,7 +44,7 @@ jobs:
- uses: actions/checkout@v3
- name: Install Rust
run: rustup update ${{ matrix.version }} && rustup default ${{ matrix.version }}
- run: cargo build --all --all-features --all-targets
- run: cargo check --all --all-features

miri:
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

# [0.9.7] - 2023-03-27

### Fixed

- Relaxed accidentally restricted `Send`/`Sync` bounds for `Mutex` guards

# [0.9.6] - 2023-03-13

### Fixed
Expand Down
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "spin"
version = "0.9.6"
version = "0.9.7"
authors = [
"Mathijs van de Nes <git@mathijs.vd-nes.nl>",
"John Ericson <git@JohnEricson.me>",
Expand Down Expand Up @@ -65,3 +65,11 @@ portable_atomic = ["portable-atomic"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dev-dependencies]
criterion = "0.4"

[[bench]]
name = "mutex"
harness = false
required-features = ["ticket_mutex"]
126 changes: 126 additions & 0 deletions benches/mutex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#[macro_use]
extern crate criterion;

use criterion::{Criterion, Bencher, black_box};
use std::{
ops::DerefMut,
sync::Arc,
};

trait Mutex<T>: Send + Sync + 'static {
type Guard<'a>: DerefMut<Target = T> where Self: 'a;
fn new(x: T) -> Self;
fn lock(&self) -> Self::Guard<'_>;
}

impl<T: Send + 'static> Mutex<T> for spin::mutex::SpinMutex<T> {
type Guard<'a> = spin::mutex::SpinMutexGuard<'a, T> where Self: 'a;
fn new(x: T) -> Self { spin::mutex::SpinMutex::new(x) }
fn lock(&self) -> Self::Guard<'_> { self.lock() }
}

impl<T: Send + 'static> Mutex<T> for spin::mutex::TicketMutex<T> {
type Guard<'a> = spin::mutex::TicketMutexGuard<'a, T> where Self: 'a;
fn new(x: T) -> Self { spin::mutex::TicketMutex::new(x) }
fn lock(&self) -> Self::Guard<'_> { self.lock() }
}

impl<T: Send + 'static> Mutex<T> for std::sync::Mutex<T> {
type Guard<'a> = std::sync::MutexGuard<'a, T> where Self: 'a;
fn new(x: T) -> Self { std::sync::Mutex::new(x) }
fn lock(&self) -> Self::Guard<'_> { self.lock().unwrap() }
}

fn gen_create<M: Mutex<u32>>(b: &mut Bencher) {
b.iter(|| {
let n = black_box(42);
M::new(n)
});
}

fn gen_lock_unlock<M: Mutex<u32>>(b: &mut Bencher) {
let m = M::new(0);
b.iter(|| {
let mut m = m.lock();
*m = m.wrapping_add(1);
drop(m);
});
}

fn gen_lock_unlock_read_contention<M: Mutex<u32>>(b: &mut Bencher) {
let m = Arc::new(M::new(0));
let thread = std::thread::spawn({
let m = m.clone();
move || {
while Arc::strong_count(&m) > 1 {
for _ in 0..1000 {
black_box(*m.lock());
}
}
}
});
b.iter(|| {
let mut m = m.lock();
*m = m.wrapping_add(1);
drop(m);
});
drop(m);
thread.join().unwrap();
}

fn gen_lock_unlock_write_contention<M: Mutex<u32>>(b: &mut Bencher) {
let m = Arc::new(M::new(0));
let thread = std::thread::spawn({
let m = m.clone();
move || {
while Arc::strong_count(&m) > 1 {
for _ in 0..1000 {
let mut m = m.lock();
*m = m.wrapping_add(1);
drop(m);
}
}
}
});
b.iter(|| {
let mut m = m.lock();
*m = m.wrapping_add(1);
drop(m);
});
drop(m);
thread.join().unwrap();
}

fn create(b: &mut Criterion) {
b.bench_function("create-spin-spinmutex", |b| gen_create::<spin::mutex::SpinMutex<u32>>(b));
b.bench_function("create-spin-ticketmutex", |b| gen_create::<spin::mutex::TicketMutex<u32>>(b));
b.bench_function("create-std", |b| gen_create::<std::sync::Mutex<u32>>(b));
}

fn lock_unlock(b: &mut Criterion) {
b.bench_function("lock_unlock-spin-spinmutex", |b| gen_lock_unlock::<spin::mutex::SpinMutex<u32>>(b));
b.bench_function("lock_unlock-spin-ticketmutex", |b| gen_lock_unlock::<spin::mutex::TicketMutex<u32>>(b));
b.bench_function("lock_unlock-std", |b| gen_lock_unlock::<std::sync::Mutex<u32>>(b));
}

fn lock_unlock_read_contention(b: &mut Criterion) {
b.bench_function("lock_unlock_read_contention-spin-spinmutex", |b| gen_lock_unlock_read_contention::<spin::mutex::SpinMutex<u32>>(b));
b.bench_function("lock_unlock_read_contention-spin-ticketmutex", |b| gen_lock_unlock_read_contention::<spin::mutex::TicketMutex<u32>>(b));
b.bench_function("lock_unlock_read_contention-std", |b| gen_lock_unlock_read_contention::<std::sync::Mutex<u32>>(b));
}

fn lock_unlock_write_contention(b: &mut Criterion) {
b.bench_function("lock_unlock_write_contention-spin-spinmutex", |b| gen_lock_unlock_write_contention::<spin::mutex::SpinMutex<u32>>(b));
b.bench_function("lock_unlock_write_contention-spin-ticketmutex", |b| gen_lock_unlock_write_contention::<spin::mutex::TicketMutex<u32>>(b));
b.bench_function("lock_unlock_write_contention-std", |b| gen_lock_unlock_write_contention::<std::sync::Mutex<u32>>(b));
}

criterion_group!(
mutex,
create,
lock_unlock,
lock_unlock_read_contention,
lock_unlock_write_contention,
);

criterion_main!(mutex);

0 comments on commit 907a550

Please sign in to comment.