-
Notifications
You must be signed in to change notification settings - Fork 328
Macro bench_specializations
#786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,3 +71,7 @@ harness = false | |
[[bench]] | ||
name = "powerset" | ||
harness = false | ||
|
||
[[bench]] | ||
name = "specializations" | ||
harness = false |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
use criterion::black_box; | ||
use itertools::iproduct; | ||
use itertools::Itertools; | ||
|
||
/// Create multiple functions each defining a benchmark group about iterator methods. | ||
/// | ||
/// Each created group has functions with the following ids: | ||
/// | ||
/// - `next`, `size_hint`, `count`, `last`, `nth`, `collect`, `fold` | ||
/// - and when marked as `DoubleEndedIterator`: `next_back`, `rfold` | ||
/// - and when marked as `ExactSizeIterator`: `len` | ||
/// | ||
/// Note that this macro can be called only once. | ||
macro_rules! bench_specializations { | ||
( | ||
$( | ||
$name:ident { | ||
$($extra:ident)* | ||
{$( | ||
$init:stmt; | ||
)*} | ||
$iterator:expr | ||
} | ||
)* | ||
) => { | ||
$( | ||
fn $name(c: &mut ::criterion::Criterion) { | ||
let mut bench_group = c.benchmark_group(stringify!($name)); | ||
$( | ||
$init | ||
)* | ||
let bench_first_its = { | ||
let mut bench_idx = 0; | ||
[0; 1000].map(|_| { | ||
let mut it = $iterator; | ||
if bench_idx != 0 { | ||
it.nth(bench_idx - 1); | ||
} | ||
bench_idx += 1; | ||
it | ||
}) | ||
}; | ||
bench_specializations!(@Iterator bench_group bench_first_its: $iterator); | ||
$( | ||
bench_specializations!(@$extra bench_group bench_first_its: $iterator); | ||
)* | ||
bench_group.finish(); | ||
} | ||
)* | ||
|
||
::criterion::criterion_group!(benches, $($name, )*); | ||
::criterion::criterion_main!(benches); | ||
}; | ||
|
||
(@Iterator $group:ident $first_its:ident: $iterator:expr) => { | ||
$group.bench_function("next", |bencher| bencher.iter(|| { | ||
let mut it = $iterator; | ||
while let Some(x) = it.next() { | ||
black_box(x); | ||
} | ||
})); | ||
$group.bench_function("size_hint", |bencher| bencher.iter(|| { | ||
$first_its.iter().for_each(|it| { | ||
black_box(it.size_hint()); | ||
}) | ||
})); | ||
$group.bench_function("count", |bencher| bencher.iter(|| { | ||
$iterator.count() | ||
})); | ||
$group.bench_function("last", |bencher| bencher.iter(|| { | ||
$iterator.last() | ||
})); | ||
$group.bench_function("nth", |bencher| bencher.iter(|| { | ||
for start in 0_usize..10 { | ||
for n in 0..10 { | ||
let mut it = $iterator; | ||
if let Some(s) = start.checked_sub(1) { | ||
black_box(it.nth(s)); | ||
} | ||
while let Some(x) = it.nth(n) { | ||
black_box(x); | ||
} | ||
} | ||
} | ||
})); | ||
$group.bench_function("collect", |bencher| bencher.iter(|| { | ||
$iterator.collect::<Vec<_>>() | ||
})); | ||
$group.bench_function("fold", |bencher| bencher.iter(|| { | ||
$iterator.fold((), |(), x| { | ||
black_box(x); | ||
}) | ||
})); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this also incllude There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I listed the currently missing (stable) methods:
I'm inclined to not add them at the moment as they rely on one of |
||
|
||
(@DoubleEndedIterator $group:ident $_first_its:ident: $iterator:expr) => { | ||
$group.bench_function("next_back", |bencher| bencher.iter(|| { | ||
let mut it = $iterator; | ||
while let Some(x) = it.next_back() { | ||
black_box(x); | ||
} | ||
})); | ||
$group.bench_function("nth_back", |bencher| bencher.iter(|| { | ||
for start in 0_usize..10 { | ||
for n in 0..10 { | ||
let mut it = $iterator; | ||
if let Some(s) = start.checked_sub(1) { | ||
black_box(it.nth_back(s)); | ||
} | ||
while let Some(x) = it.nth_back(n) { | ||
black_box(x); | ||
} | ||
} | ||
} | ||
})); | ||
$group.bench_function("rfold", |bencher| bencher.iter(|| { | ||
$iterator.rfold((), |(), x| { | ||
black_box(x); | ||
}) | ||
})); | ||
}; | ||
|
||
(@ExactSizeIterator $group:ident $first_its:ident: $_iterator:expr) => { | ||
$group.bench_function("len", |bencher| bencher.iter(|| { | ||
$first_its.iter().for_each(|it| { | ||
black_box(it.len()); | ||
}) | ||
})); | ||
}; | ||
} | ||
|
||
// Example: To bench only `ZipLongest::fold`, you can do | ||
// cargo bench --bench specializations zip_longest/fold | ||
bench_specializations! { | ||
cartesian_product { | ||
{ | ||
let v = black_box(vec![0; 16]); | ||
} | ||
iproduct!(&v, &v, &v) | ||
} | ||
multi_cartesian_product { | ||
{ | ||
let vs = black_box([0; 3].map(|_| vec![0; 16])); | ||
} | ||
vs.iter().multi_cartesian_product() | ||
} | ||
tuple_combinations { | ||
{ | ||
let v = black_box((0..64).collect_vec()); | ||
} | ||
v.iter().tuple_combinations::<(_, _, _, _)>() | ||
} | ||
while_some { | ||
{} | ||
(0..) | ||
.map(black_box) | ||
.map(|i| char::from_digit(i, 16)) | ||
.while_some() | ||
} | ||
with_position { | ||
ExactSizeIterator | ||
{ | ||
let v = black_box((0..10240).collect_vec()); | ||
} | ||
v.iter().with_position() | ||
} | ||
zip_longest { | ||
DoubleEndedIterator | ||
ExactSizeIterator | ||
Comment on lines
+168
to
+169
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neat idea! Maybe we should do this in specialization tests, too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like it too. |
||
{ | ||
let xs = black_box(vec![0; 1024]); | ||
let ys = black_box(vec![0; 768]); | ||
} | ||
xs.iter().zip_longest(ys.iter()) | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.