Skip to content

Commit

Permalink
make benchmarks generic over Metric
Browse files Browse the repository at this point in the history
  • Loading branch information
noib3 committed Oct 20, 2023
1 parent d585e22 commit 6f8209f
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 15 deletions.
103 changes: 103 additions & 0 deletions benches/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use criterion::{
measurement::WallTime,
BenchmarkGroup,
BenchmarkId,
Throughput,
};
use norm::CaseSensitivity;

pub trait Metric {
type Query<'a>: Copy + FromStr<'a>;

fn dist(&self, query: Self::Query<'_>, candidate: &str);
fn with_case_sensitivity(self, case_sensitivity: CaseSensitivity) -> Self;
fn with_matched_ranges(self, matched_ranges: bool) -> Self;
}

pub trait FromStr<'a> {
fn from_str(s: &'a str) -> Self;
}

#[inline]
fn bench<'a, M, C>(
group: &mut BenchmarkGroup<WallTime>,
id: BenchmarkId,
metric: &M,
query: &str,
candidates: C,
) where
M: Metric,
C: IntoIterator<Item = &'a str>,
C::IntoIter: ExactSizeIterator + Clone,
{
let candidates = candidates.into_iter();

group.throughput(Throughput::Elements(candidates.len() as u64));

group.bench_function(id, |b| {
let query = M::Query::from_str(query);

b.iter(|| {
for candidate in candidates.clone() {
metric.dist(query, candidate);
}
})
});
}

fn param(
case: CaseSensitivity,
with_ranges: bool,
suffix: Option<&str>,
) -> String {
let mut s = String::new();

let case = match case {
CaseSensitivity::Sensitive => "case_sensitive",
CaseSensitivity::Insensitive => "case_insensitive",
CaseSensitivity::Smart => "case_smart",
};

s.push_str(case);

let ranges = if with_ranges { "_with_ranges" } else { "" };

s.push_str(ranges);

if let Some(suffix) = suffix {
s.push('_');
s.push_str(suffix);
}

s
}

#[inline]
pub fn short<M: Metric>(
mut metric: M,
suffix: Option<&str>,
mut group: BenchmarkGroup<WallTime>,
) where
M: Metric,
{
for case in [
CaseSensitivity::Sensitive,
CaseSensitivity::Insensitive,
CaseSensitivity::Smart,
] {
for ranges in [true, false] {
let id = BenchmarkId::new("short", param(case, ranges, suffix));

metric =
metric.with_case_sensitivity(case).with_matched_ranges(ranges);

bench(
&mut group,
id,
&metric,
"jelly",
core::iter::once("jellyfish"),
);
}
}
}
38 changes: 23 additions & 15 deletions benches/fzf_v1.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod common;

use common as bench;
use criterion::{
criterion_group,
criterion_main,
measurement::WallTime,
Bencher,
BenchmarkGroup,
Criterion,
};
Expand All @@ -12,28 +14,34 @@ use norm::{
Metric,
};

fn short(fzf: &FzfV1, b: &mut Bencher) {
let jelly = FzfQuery::new("jelly");
b.iter(|| fzf.distance(jelly, "jellyfish"))
}

fn sensitive_with_ranges() -> FzfV1 {
FzfV1::new()
.with_case_sensitivity(CaseSensitivity::Sensitive)
.with_matched_ranges(true)
impl<'a> bench::FromStr<'a> for FzfQuery<'a> {
fn from_str(s: &'a str) -> Self {
FzfQuery::new(s)
}
}

fn short_case_sensitive_with_ranges(c: &mut Criterion) {
let fzf = sensitive_with_ranges();
impl bench::Metric for FzfV1 {
type Query<'a> = FzfQuery<'a>;

group(c).bench_function("short_case_sensitive_with_ranges", |b| {
short(&fzf, b)
});
#[inline]
fn dist(&self, query: FzfQuery, candidate: &str) {
self.distance(query, candidate);
}
fn with_case_sensitivity(self, case_sensitivity: CaseSensitivity) -> Self {
self.with_case_sensitivity(case_sensitivity)
}
fn with_matched_ranges(self, matched_ranges: bool) -> Self {
self.with_matched_ranges(matched_ranges)
}
}

fn group(c: &mut Criterion) -> BenchmarkGroup<WallTime> {
c.benchmark_group("fzf_v1")
}

fn short_case_sensitive_with_ranges(c: &mut Criterion) {
bench::short(FzfV1::new(), None, group(c));
}

criterion_group!(benches, short_case_sensitive_with_ranges);
criterion_main!(benches);

0 comments on commit 6f8209f

Please sign in to comment.