Skip to content

[Draft] Testing a "faster" fold #2

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 14 additions & 15 deletions iterators/benches/benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use iterators::{
filter_map_filter_callback, filter_map_filter_inline, fold_callback, fold_inline,
for_loop_callback, for_loop_inline,
};
use iterators::*;

pub fn criterion_benchmark(c: &mut Criterion) {
let nums = black_box((0..100_000).collect::<Vec<u64>>());

let mut group = c.benchmark_group("Iterators");
group.bench_function("filter-map-filter with inline logic", |b| {
group.bench_function("filter-map-filter", |b| {
b.iter(|| filter_map_filter_inline(&nums))
});
group.bench_function("filter-map-filter with callbacks", |b| {
b.iter(|| filter_map_filter_callback(&nums))
});
group.bench_function("fold with inline logic", |b| b.iter(|| fold_inline(&nums)));
group.bench_function("fold with callbacks", |b| b.iter(|| fold_callback(&nums)));
group.bench_function("for loop with inline logic", |b| {
b.iter(|| for_loop_inline(&nums))
});
group.bench_function("for loop with callbacks", |b| {
b.iter(|| for_loop_callback(&nums))
// group.bench_function("filter-map-filter with callbacks", |b| {
// b.iter(|| filter_map_filter_callback(&nums))
// });
group.bench_function("fold", |b| b.iter(|| fold_inline(&nums)));
// group.bench_function("fold with callbacks", |b| b.iter(|| fold_callback(&nums)));
group.bench_function("for loop", |b| b.iter(|| for_loop_inline(&nums)));
// group.bench_function("for loop with callbacks", |b| {
// b.iter(|| for_loop_callback(&nums))
// });
group.bench_function("fold_mut", |b| b.iter(|| fold_custom(&nums)));
group.bench_function("fold_mut implemented with fold", |b| {
b.iter(|| fold_custom_2(&nums))
});
group.finish();
}
Expand Down
60 changes: 60 additions & 0 deletions iterators/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,58 @@ pub fn fold_inline(nums: &[u64]) -> Vec<u64> {
})
}

struct Foo<I: Iterator<Item = u64>> {
inner: I,
}
impl<I: Iterator<Item = u64>> Foo<I> {
fn fold_custom<F>(mut self, init: Vec<u64>, mut f: F) -> Vec<u64>
where
F: FnMut(&mut Vec<u64>, u64),
{
let mut accum = init;
while let Some(x) = self.inner.next() {
f(&mut accum, x);
}
accum
}
fn fold_custom_2<F>(self, init: Vec<u64>, mut f: F) -> Vec<u64>
where
F: FnMut(&mut Vec<u64>, u64),
{
self.inner.fold(init, |mut acc, x| {
f(&mut acc, x);
acc
})
}
}

pub fn fold_custom(nums: &[u64]) -> Vec<u64> {
let foo = Foo {
inner: nums.iter().copied(),
};
foo.fold_custom(Vec::new(), |result, n| {
if n % 3 == 0 {
let high_bits = n & (255 << 8);
if high_bits % 3 == 0 {
result.push(high_bits);
}
}
})
}
pub fn fold_custom_2(nums: &[u64]) -> Vec<u64> {
let foo = Foo {
inner: nums.iter().copied(),
};
foo.fold_custom_2(Vec::new(), |result, n| {
if n % 3 == 0 {
let high_bits = n & (255 << 8);
if high_bits % 3 == 0 {
result.push(high_bits);
}
}
})
}

pub fn for_loop_inline(nums: &[u64]) -> Vec<u64> {
let mut result = Vec::new();
for n in nums {
Expand Down Expand Up @@ -128,4 +180,12 @@ mod tests {
vec![0, 3 << 8, 6 << 8]
)
}

#[test]
fn fold_custom_works() {
assert_eq!(
fold_custom(&[0, (3 << 8) | 3, (4 << 8) + 2, (3 << 8) + 1, (6 << 8) | 3]),
vec![0, 3 << 8, 6 << 8]
)
}
}
4 changes: 4 additions & 0 deletions iterators/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fn main() {
let multiple_inline_time = time_function(&nums, filter_map_filter_inline);
let single_inline_time = time_function(&nums, fold_inline);
let single_loop_inline_time = time_function(&nums, for_loop_inline);
let fold_custom_time = time_function(&nums, fold_custom);

println!("Times (sec):");
println!("{0: <20}{1:}", "Multiple:", multiple_time);
Expand All @@ -41,13 +42,15 @@ fn main() {
println!("{0: <20}{1:}", "Multiple Inline:", multiple_inline_time);
println!("{0: <20}{1:}", "Single Inline:", single_inline_time);
println!("{0: <20}{1:}", "Loop Inline:", single_loop_inline_time);
println!("{0: <20}{1:}", "Fold Custom:", fold_custom_time);

let multiple_weight = weigh_function(&nums, filter_map_filter_callback);
let single_weight = weigh_function(&nums, fold_callback);
let single_loop_weight = weigh_function(&nums, for_loop_callback);
let multiple_inline_weight = weigh_function(&nums, filter_map_filter_inline);
let single_inline_weight = weigh_function(&nums, fold_inline);
let single_loop_inline_weight = weigh_function(&nums, for_loop_inline);
let fold_custom_weight = weigh_function(&nums, fold_custom);

println!("\nWeights (bytes):");
println!("{0: <20}{1:}", "Multiple:", multiple_weight);
Expand All @@ -56,6 +59,7 @@ fn main() {
println!("{0: <20}{1:}", "Multiple Inline:", multiple_inline_weight);
println!("{0: <20}{1:}", "Single Inline:", single_inline_weight);
println!("{0: <20}{1:}", "Loop Inline:", single_loop_inline_weight);
println!("{0: <20}{1:}", "Fold Custom:", fold_custom_weight);
}

type Func = fn(args: &[u64]) -> Vec<u64>;
Expand Down