Skip to content

Commit

Permalink
feat: add benchmarks
Browse files Browse the repository at this point in the history
fix: fmt & exclude benchmarks from ci

fix: fmt
  • Loading branch information
Konippi committed Jul 28, 2024
1 parent eb049a8 commit f6c6db2
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ jobs:
- uses: actions/checkout@v4
- run: rustup update stable && rustup default stable
- run: rustup component add clippy
- run: cargo clippy --workspace --all-targets --no-deps
- run: cargo clippy --lib --bins --tests --examples --no-deps
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ default = ["std"]
std = []
nightly = []
rand = ["dep:rand", "std"]
std_bench = ["nightly"]

[dependencies]
rand = { version = "0.8", optional = true }
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,56 @@ It can be turned off in `Cargo.toml` like so:
```toml
rustc-hash = { version = "2.0", default-features = false }
```

## Benchmarks

The benchmarks are run with the following command:

- `rustc-hash::FxHashMap`

```console
> cargo +nightly bench

test fx_benchmarks::bench_hashmap_create ... bench: 2.08 ns/iter (+/- 0.04)
test fx_benchmarks::bench_hashmap_insert ... bench: 175.02 ns/iter (+/- 5.89)
test fx_benchmarks::bench_hashmap_insert_large_data ... bench: 16,121,283.40 ns/iter (+/- 2,276,733.63)
test fx_benchmarks::bench_hashmap_iter ... bench: 2.05 ns/iter (+/- 0.07)
test fx_benchmarks::bench_hashmap_iter_large_data ... bench: 173,197.71 ns/iter (+/- 3,914.19)
test fx_benchmarks::bench_hashmap_lookup ... bench: 2.44 ns/iter (+/- 0.11)
test fx_benchmarks::bench_hashmap_lookup_large_data ... bench: 444,745.90 ns/iter (+/- 91,353.67)
test fx_benchmarks::bench_hashmap_reinsert ... bench: 67.53 ns/iter (+/- 5.21)
test fx_benchmarks::bench_hashmap_reinsert_large_data ... bench: 12,455,191.70 ns/iter (+/- 9,219,748.08)
test fx_benchmarks::bench_hashmap_remove ... bench: 4.95 ns/iter (+/- 0.17)
test fx_benchmarks::bench_hashmap_remove_large_data ... bench: 561,822.95 ns/iter (+/- 14,508.17)
test fx_benchmarks::bench_hashmap_with_mutex ... bench: 77.26 ns/iter (+/- 15.62)
test fx_benchmarks::bench_hashmap_with_mutex_large_data ... bench: 13,674,849.90 ns/iter (+/- 9,925,902.12)
test fx_benchmarks::bench_hashmap_with_rwlock ... bench: 73.16 ns/iter (+/- 2.48)
test fx_benchmarks::bench_hashmap_with_rwlock_large_data ... bench: 12,159,066.70 ns/iter (+/- 9,738,272.64)

test result: ok. 0 passed; 0 failed; 0 ignored; 15 measured; 0 filtered out; finished in 37.61s
```

- `std::collections::HashMap`

```console
> cargo +nightly bench --features=std-bench

...
test std_benchmarks::bench_hashmap_create ... bench: 9.20 ns/iter (+/- 0.14)
test std_benchmarks::bench_hashmap_insert ... bench: 195.85 ns/iter (+/- 6.37)
test std_benchmarks::bench_hashmap_insert_large_data ... bench: 21,693,487.50 ns/iter (+/- 3,609,774.56)
test std_benchmarks::bench_hashmap_iter ... bench: 2.08 ns/iter (+/- 0.05)
test std_benchmarks::bench_hashmap_iter_large_data ... bench: 226,075.13 ns/iter (+/- 9,295.55)
test std_benchmarks::bench_hashmap_lookup ... bench: 16.44 ns/iter (+/- 0.37)
test std_benchmarks::bench_hashmap_lookup_large_data ... bench: 2,456,185.40 ns/iter (+/- 109,599.74)
test std_benchmarks::bench_hashmap_reinsert ... bench: 84.26 ns/iter (+/- 2.26)
test std_benchmarks::bench_hashmap_reinsert_large_data ... bench: 10,378,541.70 ns/iter (+/- 5,037,469.76)
test std_benchmarks::bench_hashmap_remove ... bench: 17.83 ns/iter (+/- 0.13)
test std_benchmarks::bench_hashmap_remove_large_data ... bench: 3,100,606.20 ns/iter (+/- 28,839.83)
test std_benchmarks::bench_hashmap_with_mutex ... bench: 96.03 ns/iter (+/- 4.22)
test std_benchmarks::bench_hashmap_with_mutex_large_data ... bench: 11,495,400.00 ns/iter (+/- 4,018,753.31)
test std_benchmarks::bench_hashmap_with_rwlock ... bench: 89.40 ns/iter (+/- 3.91)
test std_benchmarks::bench_hashmap_with_rwlock_large_data ... bench: 12,300,512.40 ns/iter (+/- 11,790,539.19)

test result: ok. 0 passed; 0 failed; 0 ignored; 15 measured; 0 filtered out; finished in 42.77s
```
197 changes: 197 additions & 0 deletions benches/benchmarks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#![cfg(feature = "nightly")]
#![feature(test)]

extern crate test;

use std::sync::{Arc, Mutex, RwLock};
use test::{black_box, Bencher};

#[cfg(not(feature = "std_bench"))]
use rustc_hash::FxHashMap;

#[cfg(feature = "std_bench")]
use std::collections::HashMap;

const LARGE_ITEM_SIZE: usize = 100000;

macro_rules! benchmarks {
($map_type:ty,$map_creater:expr) => {
// Benchmark for creating a FxHashMap.
#[bench]
fn bench_hashmap_create(b: &mut Bencher) {
b.iter(|| {
let map: $map_type = $map_creater();
black_box(map)
});
}

// Benchmark for inserting items into a FxHashMap.
#[bench]
fn bench_hashmap_insert(b: &mut Bencher) {
b.iter(|| {
let mut map = $map_creater();
map.insert(1, 1.to_string());
black_box(map)
});
}

#[bench]
fn bench_hashmap_insert_large_data(b: &mut Bencher) {
b.iter(|| {
let mut map = $map_creater();
for i in 0..LARGE_ITEM_SIZE {
map.insert(i, i.to_string());
}
black_box(map)
});
}

// Benchmark for looking up items in a FxHashMap.
#[bench]
fn bench_hashmap_lookup(b: &mut Bencher) {
let mut map = $map_creater();
map.insert(1, 1.to_string());
b.iter(|| {
black_box(map.get(&1));
});
}

#[bench]
fn bench_hashmap_lookup_large_data(b: &mut Bencher) {
let mut map = $map_creater();
for i in 0..LARGE_ITEM_SIZE {
map.insert(i, i.to_string());
}
b.iter(|| {
for i in 0..LARGE_ITEM_SIZE {
black_box(map.get(&i));
}
});
}

// Benchmark for removing items from a FxHashMap.
#[bench]
fn bench_hashmap_remove(b: &mut Bencher) {
let mut map = $map_creater();
map.insert(1, 1.to_string());
b.iter(|| {
black_box(map.remove(&1));
});
}

#[bench]
fn bench_hashmap_remove_large_data(b: &mut Bencher) {
let mut map = $map_creater();
for i in 0..LARGE_ITEM_SIZE {
map.insert(i, i.to_string());
}
b.iter(|| {
for i in 0..LARGE_ITEM_SIZE {
black_box(map.remove(&i));
}
});
}

// Benchmark for iterating over a FxHashMap.
#[bench]
fn bench_hashmap_iter(b: &mut Bencher) {
let mut map = $map_creater();
map.insert(1, 1.to_string());
b.iter(|| {
for (k, v) in &map {
black_box((k, v));
}
});
}

#[bench]
fn bench_hashmap_iter_large_data(b: &mut Bencher) {
let mut map = $map_creater();
for i in 0..LARGE_ITEM_SIZE {
map.insert(i, i.to_string());
}
b.iter(|| {
for (k, v) in &map {
black_box((k, v));
}
});
}

// Benchmark for reinserting items into a FxHashMap.
#[bench]
fn bench_hashmap_reinsert(b: &mut Bencher) {
let mut map = $map_creater();
map.insert(1, 1.to_string());
b.iter(|| {
map.insert(1, 2.to_string());
});
}

#[bench]
fn bench_hashmap_reinsert_large_data(b: &mut Bencher) {
let mut map = $map_creater();
for i in 0..LARGE_ITEM_SIZE {
map.insert(i, i.to_string());
}
b.iter(|| {
for i in 0..LARGE_ITEM_SIZE {
map.insert(i, (i + 1).to_string());
}
});
}

// Benchmark for inserting items into a FxHashMap with a Mutex.
#[bench]
fn bench_hashmap_with_mutex(b: &mut Bencher) {
let map = Arc::new(Mutex::new($map_creater()));
b.iter(|| {
let mut locked_map = map.lock().unwrap();
locked_map.insert(1, 1.to_string());
});
}

#[bench]
fn bench_hashmap_with_mutex_large_data(b: &mut Bencher) {
let map = Arc::new(Mutex::new($map_creater()));
b.iter(|| {
for i in 0..LARGE_ITEM_SIZE {
let mut locked_map = map.lock().unwrap();
locked_map.insert(i, i.to_string());
}
});
}

// Benchmark for inserting items into a FxHashMap with a RwLock.
#[bench]
fn bench_hashmap_with_rwlock(b: &mut Bencher) {
let map = Arc::new(RwLock::new($map_creater()));
b.iter(|| {
let mut locked_map = map.write().unwrap();
locked_map.insert(1, 1.to_string());
});
}

#[bench]
fn bench_hashmap_with_rwlock_large_data(b: &mut Bencher) {
let map = Arc::new(RwLock::new($map_creater()));
b.iter(|| {
for i in 0..LARGE_ITEM_SIZE {
let mut locked_map = map.write().unwrap();
locked_map.insert(i, i.to_string());
}
});
}
};
}

#[cfg(not(feature = "std_bench"))]
mod fx_benchmarks {
use super::*;
benchmarks!(FxHashMap<i32, String>, || FxHashMap::default());
}

#[cfg(feature = "std_bench")]
mod std_benchmarks {
use super::*;
benchmarks!(HashMap<i32, String>,|| HashMap::new());
}

0 comments on commit f6c6db2

Please sign in to comment.