Skip to content

Commit 8721a85

Browse files
authored
Merge pull request #141 from cdellacqua/main
Increase copy speed by orders of magnitude
2 parents edefbb7 + d658362 commit 8721a85

File tree

7 files changed

+1026
-6
lines changed

7 files changed

+1026
-6
lines changed

benches/bench.rs

Lines changed: 213 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(coverage_attribute)]
22
#![coverage(off)]
33
use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion};
4-
use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, RingBuffer};
4+
use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, RingBuffer, SetLen};
55

66
fn benchmark_push<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
77
b.iter(|| {
@@ -74,6 +74,89 @@ fn benchmark_skip<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
7474
})
7575
}
7676

77+
fn benchmark_copy_to_slice_vs_extend<T: RingBuffer<i32>, F: Fn() -> T>(
78+
rb_size: usize,
79+
rb_type: &str,
80+
fn_name: &str,
81+
c: &mut Criterion,
82+
new: F,
83+
) {
84+
let mut group = c.benchmark_group(format!("{fn_name}({rb_type}, {rb_size})"));
85+
let mut output = vec![0; rb_size];
86+
group.bench_function(format!("CopyTo({rb_type}; {rb_size})"), |b| {
87+
let mut rb = new();
88+
rb.fill(9);
89+
// making sure the read/write pointers wrap around
90+
for _ in 0..rb_size / 2 {
91+
let _ = rb.dequeue();
92+
let _ = rb.enqueue(9);
93+
}
94+
b.iter(|| {
95+
rb.copy_to_slice(0, &mut output);
96+
assert_eq!(output[output.len() / 2], 9);
97+
assert_eq!(output.len(), rb_size);
98+
})
99+
});
100+
let mut output: Vec<i32> = Vec::with_capacity(rb_size);
101+
group.bench_function(format!("ExtendVec({rb_type}; {rb_size})"), |b| {
102+
let mut rb = new();
103+
rb.fill(9);
104+
// making sure the read/write pointers wrap around
105+
for _ in 0..rb_size / 2 {
106+
let _ = rb.dequeue();
107+
let _ = rb.enqueue(9);
108+
}
109+
b.iter(|| {
110+
unsafe { output.set_len(0) };
111+
output.extend(rb.iter());
112+
assert_eq!(output[output.len() / 2], 9);
113+
assert_eq!(output.len(), rb_size);
114+
})
115+
});
116+
group.finish();
117+
}
118+
119+
fn benchmark_copy_from_slice_vs_extend<T: RingBuffer<i32> + SetLen, F: Fn() -> T>(
120+
rb_size: usize,
121+
rb_type: &str,
122+
fn_name: &str,
123+
c: &mut Criterion,
124+
new: F,
125+
) {
126+
let mut group = c.benchmark_group(format!("{fn_name}({rb_type}, {rb_size})"));
127+
let input = vec![9; rb_size];
128+
group.bench_function(format!("CopyFrom({rb_type}; {rb_size})"), |b| {
129+
let mut rb = new();
130+
rb.fill(0);
131+
// making sure the read/write pointers wrap around
132+
for _ in 0..rb_size / 2 {
133+
let _ = rb.dequeue();
134+
let _ = rb.enqueue(0);
135+
}
136+
for _ in 0..rb_size / 2 {}
137+
b.iter(|| {
138+
rb.copy_from_slice(0, &input);
139+
assert_eq!(rb[rb.len() / 2], 9);
140+
assert_eq!(rb.len(), rb_size);
141+
})
142+
});
143+
group.bench_function(format!("ExtendRb({rb_type}; {rb_size})"), |b| {
144+
let mut rb = new();
145+
// making sure the read/write pointers wrap around
146+
for _ in 0..rb_size / 2 {
147+
let _ = rb.dequeue();
148+
let _ = rb.enqueue(0);
149+
}
150+
b.iter(|| {
151+
unsafe { rb.set_len(0) };
152+
rb.extend(input.iter().copied());
153+
assert_eq!(rb[rb.len() / 2], 9);
154+
assert_eq!(rb.len(), rb_size);
155+
})
156+
});
157+
group.finish();
158+
}
159+
77160
macro_rules! generate_benches {
78161
(called, $c: tt, $rb: tt, $ty: tt, $fn: tt, $bmfunc: tt, $($i:tt),*) => {
79162
$(
@@ -97,6 +180,22 @@ macro_rules! generate_benches {
97180
}));
98181
)*
99182
};
183+
184+
(compare, $c: tt, $rb: tt, $ty: tt, $fn: tt, $bmfunc: tt, $($i:tt),*) => {
185+
$(
186+
$bmfunc($i, stringify!($rb), stringify!($bmfunc), $c, || {
187+
$rb::<$ty>::$fn($i)
188+
});
189+
)*
190+
};
191+
192+
(compare_typed, $c: tt, $rb: tt, $ty: tt, $fn: tt, $bmfunc: tt, $($i:tt),*) => {
193+
$(
194+
$bmfunc($i, stringify!($rb), stringify!($bmfunc), $c, || {
195+
$rb::<$ty, $i>::$fn()
196+
});
197+
)*
198+
};
100199
}
101200

102201
fn criterion_benchmark(c: &mut Criterion) {
@@ -217,6 +316,119 @@ fn criterion_benchmark(c: &mut Criterion) {
217316
8192,
218317
8195
219318
];
319+
generate_benches![
320+
compare,
321+
c,
322+
AllocRingBuffer,
323+
i32,
324+
new,
325+
benchmark_copy_to_slice_vs_extend,
326+
16,
327+
1024,
328+
4096,
329+
8192,
330+
1_000_000,
331+
1_048_576
332+
];
333+
generate_benches![
334+
compare_typed,
335+
c,
336+
ConstGenericRingBuffer,
337+
i32,
338+
new,
339+
benchmark_copy_to_slice_vs_extend,
340+
16,
341+
1024,
342+
4096,
343+
8192,
344+
1_000_000,
345+
1_048_576
346+
];
347+
generate_benches![
348+
compare,
349+
c,
350+
AllocRingBuffer,
351+
i32,
352+
new,
353+
benchmark_copy_from_slice_vs_extend,
354+
16,
355+
1024,
356+
4096,
357+
8192,
358+
1_000_000,
359+
1_048_576
360+
];
361+
generate_benches![
362+
compare_typed,
363+
c,
364+
ConstGenericRingBuffer,
365+
i32,
366+
new,
367+
benchmark_copy_from_slice_vs_extend,
368+
16,
369+
1024,
370+
4096,
371+
8192,
372+
1_000_000,
373+
1_048_576
374+
];
375+
376+
generate_benches![
377+
compare,
378+
c,
379+
AllocRingBuffer,
380+
i32,
381+
new,
382+
benchmark_copy_to_slice_vs_extend,
383+
16,
384+
1024,
385+
4096,
386+
8192,
387+
1_000_000,
388+
1_048_576
389+
];
390+
generate_benches![
391+
compare_typed,
392+
c,
393+
ConstGenericRingBuffer,
394+
i32,
395+
new,
396+
benchmark_copy_to_slice_vs_extend,
397+
16,
398+
1024,
399+
4096,
400+
8192,
401+
1_000_000,
402+
1_048_576
403+
];
404+
generate_benches![
405+
compare,
406+
c,
407+
AllocRingBuffer,
408+
i32,
409+
new,
410+
benchmark_copy_from_slice_vs_extend,
411+
16,
412+
1024,
413+
4096,
414+
8192,
415+
1_000_000,
416+
1_048_576
417+
];
418+
generate_benches![
419+
compare_typed,
420+
c,
421+
ConstGenericRingBuffer,
422+
i32,
423+
new,
424+
benchmark_copy_from_slice_vs_extend,
425+
16,
426+
1024,
427+
4096,
428+
8192,
429+
1_000_000,
430+
1_048_576
431+
];
220432
}
221433

222434
criterion_group!(benches, criterion_benchmark);

0 commit comments

Comments
 (0)