|
12 | 12 | // See the License for the specific language governing permissions and
|
13 | 13 | // limitations under the License.
|
14 | 14 |
|
15 |
| -use std::{ |
16 |
| - sync::Arc, |
17 |
| - time::{Duration, Instant}, |
18 |
| -}; |
19 |
| - |
20 |
| -use rand::{distributions::Alphanumeric, thread_rng, Rng}; |
21 |
| - |
22 |
| -struct T<F> |
23 |
| -where |
24 |
| - F: Fn(&str) -> usize, |
25 |
| -{ |
26 |
| - f1: F, |
27 |
| - f2: Box<dyn Fn(&str) -> usize>, |
28 |
| - f3: Arc<dyn Fn(&str) -> usize>, |
| 15 | +use criterion::{criterion_group, criterion_main, Criterion}; |
| 16 | +use std::sync::Arc; |
| 17 | + |
| 18 | +pub trait Processor { |
| 19 | + fn process(&self) -> usize; |
29 | 20 | }
|
30 | 21 |
|
31 |
| -fn rand_string(len: usize) -> String { |
32 |
| - thread_rng() |
33 |
| - .sample_iter(&Alphanumeric) |
34 |
| - .take(len) |
35 |
| - .map(char::from) |
36 |
| - .collect() |
| 22 | +pub struct SimpleProcessor { |
| 23 | + data: usize, |
37 | 24 | }
|
38 | 25 |
|
39 |
| -fn bench_static_dispatch<F>(t: &T<F>, loops: usize) -> Duration |
40 |
| -where |
41 |
| - F: Fn(&str) -> usize, |
42 |
| -{ |
43 |
| - let mut dur = Duration::default(); |
44 |
| - for _ in 0..loops { |
45 |
| - let s = rand_string(thread_rng().gen_range(0..100)); |
46 |
| - let now = Instant::now(); |
47 |
| - let _ = (t.f1)(&s); |
48 |
| - dur += now.elapsed(); |
| 26 | +impl SimpleProcessor { |
| 27 | + pub fn new(data: usize) -> Self { |
| 28 | + SimpleProcessor { data } |
49 | 29 | }
|
50 |
| - Duration::from_nanos((dur.as_nanos() as usize / loops) as _) |
51 | 30 | }
|
52 | 31 |
|
53 |
| -fn bench_box_dynamic_dispatch<F>(t: &T<F>, loops: usize) -> Duration |
54 |
| -where |
55 |
| - F: Fn(&str) -> usize, |
56 |
| -{ |
57 |
| - let mut dur = Duration::default(); |
58 |
| - for _ in 0..loops { |
59 |
| - let s = rand_string(thread_rng().gen_range(0..100)); |
60 |
| - let now = Instant::now(); |
61 |
| - let _ = (t.f3)(&s); |
62 |
| - dur += now.elapsed(); |
| 32 | +impl Processor for SimpleProcessor { |
| 33 | + fn process(&self) -> usize { |
| 34 | + self.data * self.data |
63 | 35 | }
|
64 |
| - Duration::from_nanos((dur.as_nanos() as usize / loops) as _) |
65 | 36 | }
|
66 | 37 |
|
67 |
| -fn bench_arc_dynamic_dispatch<F>(t: &T<F>, loops: usize) -> Duration |
68 |
| -where |
69 |
| - F: Fn(&str) -> usize, |
70 |
| -{ |
71 |
| - let mut dur = Duration::default(); |
72 |
| - for _ in 0..loops { |
73 |
| - let s = rand_string(thread_rng().gen_range(0..100)); |
74 |
| - let now = Instant::now(); |
75 |
| - let _ = (t.f2)(&s); |
76 |
| - dur += now.elapsed(); |
| 38 | +pub struct ComplexProcessor { |
| 39 | + data: Vec<usize>, |
| 40 | +} |
| 41 | + |
| 42 | +impl ComplexProcessor { |
| 43 | + pub fn new(data: Vec<usize>) -> Self { |
| 44 | + ComplexProcessor { data } |
77 | 45 | }
|
78 |
| - Duration::from_nanos((dur.as_nanos() as usize / loops) as _) |
79 | 46 | }
|
80 | 47 |
|
81 |
| -fn main() { |
82 |
| - let t = T { |
83 |
| - f1: |s: &str| s.len(), |
84 |
| - f2: Box::new(|s: &str| s.len()), |
85 |
| - f3: Arc::new(|s: &str| s.len()), |
86 |
| - }; |
87 |
| - |
88 |
| - let _ = T { |
89 |
| - f1: |s: &str| s.len(), |
90 |
| - f2: Box::new(|s: &str| s.len() + 1), |
91 |
| - f3: Arc::new(|s: &str| s.len() + 1), |
92 |
| - }; |
93 |
| - |
94 |
| - let _ = T { |
95 |
| - f1: |s: &str| s.len(), |
96 |
| - f2: Box::new(|s: &str| s.len() + 2), |
97 |
| - f3: Arc::new(|s: &str| s.len() + 2), |
98 |
| - }; |
99 |
| - |
100 |
| - let _ = T { |
101 |
| - f1: |s: &str| s.len(), |
102 |
| - f2: Box::new(|s: &str| s.len() + 3), |
103 |
| - f3: Arc::new(|s: &str| s.len() + 3), |
104 |
| - }; |
105 |
| - |
106 |
| - for loops in [100_000, 1_000_000, 10_000_000] { |
107 |
| - println!(); |
108 |
| - |
109 |
| - println!(" statis - {} loops : {:?}", loops, bench_static_dispatch(&t, loops)); |
110 |
| - println!( |
111 |
| - "box dynamic - {} loops : {:?}", |
112 |
| - loops, |
113 |
| - bench_box_dynamic_dispatch(&t, loops) |
114 |
| - ); |
115 |
| - println!( |
116 |
| - "arc dynamic - {} loops : {:?}", |
117 |
| - loops, |
118 |
| - bench_arc_dynamic_dispatch(&t, loops) |
119 |
| - ); |
| 48 | +impl Processor for ComplexProcessor { |
| 49 | + fn process(&self) -> usize { |
| 50 | + self.data.iter().sum() |
120 | 51 | }
|
121 | 52 | }
|
| 53 | + |
| 54 | +fn bench_processor_types(c: &mut Criterion) { |
| 55 | + let simple_data = 42; |
| 56 | + let complex_data: Vec<usize> = (1..=10_000).collect(); |
| 57 | + |
| 58 | + let simple_processor = SimpleProcessor::new(simple_data); |
| 59 | + let box_simple_processor: Box<dyn Processor> = Box::new(SimpleProcessor::new(simple_data)); |
| 60 | + let arc_simple_processor: Arc<dyn Processor> = Arc::new(SimpleProcessor::new(simple_data)); |
| 61 | + |
| 62 | + let complex_processor = ComplexProcessor::new(complex_data.clone()); |
| 63 | + let box_complex_processor: Box<dyn Processor> = Box::new(ComplexProcessor::new(complex_data.clone())); |
| 64 | + let arc_complex_processor: Arc<dyn Processor> = Arc::new(ComplexProcessor::new(complex_data.clone())); |
| 65 | + |
| 66 | + let mut group = c.benchmark_group("Processor Types"); |
| 67 | + group.bench_function("simple_direct_reference", |b| b.iter(|| simple_processor.process())); |
| 68 | + group.bench_function("simple_box_dynamic_dispatch", |b| { |
| 69 | + b.iter(|| box_simple_processor.process()) |
| 70 | + }); |
| 71 | + group.bench_function("simple_arc_dynamic_dispatch", |b| { |
| 72 | + b.iter(|| arc_simple_processor.process()) |
| 73 | + }); |
| 74 | + |
| 75 | + group.bench_function("complex_direct_reference", |b| b.iter(|| complex_processor.process())); |
| 76 | + group.bench_function("complex_box_dynamic_dispatch", |b| { |
| 77 | + b.iter(|| box_complex_processor.process()) |
| 78 | + }); |
| 79 | + group.bench_function("complex_arc_dynamic_dispatch", |b| { |
| 80 | + b.iter(|| arc_complex_processor.process()) |
| 81 | + }); |
| 82 | + |
| 83 | + group.finish(); |
| 84 | +} |
| 85 | + |
| 86 | +/* |
| 87 | +Processor Types/simple_direct_reference time: [299.32 ps 299.45 ps 299.67 ps] |
| 88 | +simple_box_dynamic_dispatch time: [1.4963 ns 1.4969 ns 1.4980 ns] |
| 89 | +simple_arc_dynamic_dispatch time: [1.4962 ns 1.4964 ns 1.4967 ns] |
| 90 | +
|
| 91 | +complex_direct_reference time: [753.43 ns 753.53 ns 753.65 ns] |
| 92 | +complex_box_dynamic_dispatch time: [757.12 ns 757.31 ns 757.58 ns] |
| 93 | +complex_arc_dynamic_dispatch time: [757.55 ns 757.67 ns 757.84 ns] |
| 94 | +*/ |
| 95 | +criterion_group!(benches, bench_processor_types); |
| 96 | +criterion_main!(benches); |
0 commit comments