]> git.proxmox.com Git - rustc.git/blob - src/vendor/string_cache/src/bench.rs
New upstream version 1.22.1+dfsg1
[rustc.git] / src / vendor / string_cache / src / bench.rs
1 // Copyright 2014 The Servo Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 /*
11
12 A cautionary note about these benchmarks:
13
14 Many of the operations we're attempting to measure take less than one
15 nanosecond. That's why we run them thousands of times in a loop just to get a
16 single iteration that Rust's statistical benchmarking can work with. At that
17 scale, any change anywhere in the library can produce durable performance
18 regressions on the order of half a nanosecond, i.e. "500 ns" in the output for
19 a test like eq_x_1000.
20
21 We can't get anything done if we rachet on these numbers! They are more useful
22 for selecting between alternatives, and for noticing large regressions or
23 inconsistencies.
24
25 Furthermore, a large part of the point of interning is to make strings small
26 and cheap to move around, which isn't reflected in these tests.
27
28 */
29
30 use atom::tests::TestAtom;
31 use test::{Bencher, black_box};
32
33 // Just shorthand
34 fn mk(x: &str) -> TestAtom {
35 TestAtom::from(x)
36 }
37
38 macro_rules! check_type (($name:ident, $x:expr, $p:pat) => (
39 // NB: "cargo bench" does not run these!
40 #[test]
41 fn $name() {
42 match unsafe { $x.unpack() } {
43 $p => (),
44 _ => panic!("atom has wrong type"),
45 }
46 }
47 ));
48
49 macro_rules! bench_tiny_op (($name:ident, $op:ident, $ctor_x:expr, $ctor_y:expr) => (
50 #[bench]
51 fn $name(b: &mut Bencher) {
52 const n: usize = 1000;
53 let xs: Vec<_> = repeat($ctor_x).take(n).collect();
54 let ys: Vec<_> = repeat($ctor_y).take(n).collect();
55
56 b.iter(|| {
57 for (x, y) in xs.iter().zip(ys.iter()) {
58 black_box(x.$op(y));
59 }
60 });
61 }
62 ));
63
64 macro_rules! bench_one (
65 (x_static $x:expr, $y:expr) => (check_type!(check_type_x, $x, Static(..)););
66 (x_inline $x:expr, $y:expr) => (check_type!(check_type_x, $x, Inline(..)););
67 (x_dynamic $x:expr, $y:expr) => (check_type!(check_type_x, $x, Dynamic(..)););
68 (y_static $x:expr, $y:expr) => (check_type!(check_type_y, $y, Static(..)););
69 (y_inline $x:expr, $y:expr) => (check_type!(check_type_y, $y, Inline(..)););
70 (y_dynamic $x:expr, $y:expr) => (check_type!(check_type_y, $y, Dynamic(..)););
71 (is_static $x:expr, $y:expr) => (bench_one!(x_static $x, $y); bench_one!(y_static $x, $y););
72 (is_inline $x:expr, $y:expr) => (bench_one!(x_inline $x, $y); bench_one!(y_inline $x, $y););
73 (is_dynamic $x:expr, $y:expr) => (bench_one!(x_dynamic $x, $y); bench_one!(y_dynamic $x, $y););
74
75 (eq $x:expr, $_y:expr) => (bench_tiny_op!(eq_x_1000, eq, $x, $x););
76 (ne $x:expr, $y:expr) => (bench_tiny_op!(ne_x_1000, ne, $x, $y););
77 (lt $x:expr, $y:expr) => (bench_tiny_op!(lt_x_1000, lt, $x, $y););
78
79 (intern $x:expr, $_y:expr) => (
80 #[bench]
81 fn intern(b: &mut Bencher) {
82 let x = $x.to_string();
83 b.iter(|| {
84 black_box(TestAtom::from(&*x));
85 });
86 }
87 );
88
89 (as_ref $x:expr, $_y:expr) => (
90 #[bench]
91 fn as_ref_x_1000(b: &mut Bencher) {
92 let x = $x;
93 b.iter(|| {
94 for _ in 0..1000 {
95 black_box(x.as_ref());
96 }
97 });
98 }
99 );
100
101 (clone $x:expr, $_y:expr) => (
102 #[bench]
103 fn clone_x_1000(b: &mut Bencher) {
104 let x = $x;
105 b.iter(|| {
106 for _ in 0..1000 {
107 black_box(x.clone());
108 }
109 });
110 }
111 );
112
113 (clone_string $x:expr, $_y:expr) => (
114 #[bench]
115 fn clone_x_1000(b: &mut Bencher) {
116 let x = $x.to_string();
117 b.iter(|| {
118 for _ in 0..1000 {
119 black_box(x.clone());
120 }
121 });
122 }
123 );
124 );
125
126 macro_rules! bench_all (
127 ([ $($which:ident)+ ] for $name:ident = $x:expr, $y:expr) => (
128 // FIXME: This module works around rust-lang/rust#12249 so we don't
129 // have to repeat the names for eq and neq.
130 mod $name {
131 #![allow(unused_imports)]
132
133 use test::{Bencher, black_box};
134 use std::string::ToString;
135 use std::iter::repeat;
136
137 use atom::tests::TestAtom;
138 use atom::UnpackedAtom::{Static, Inline, Dynamic};
139
140 use super::mk;
141
142 $(
143 bench_one!($which $x, $y);
144 )+
145 }
146 );
147 );
148
149 pub const longer_dynamic_a: &'static str
150 = "Thee Silver Mt. Zion Memorial Orchestra & Tra-La-La Band";
151 pub const longer_dynamic_b: &'static str
152 = "Thee Silver Mt. Zion Memorial Orchestra & Tra-La-La Ban!";
153
154 bench_all!([eq ne lt clone_string] for short_string = "e", "f");
155 bench_all!([eq ne lt clone_string] for medium_string = "xyzzy01", "xyzzy02");
156 bench_all!([eq ne lt clone_string]
157 for longer_string = super::longer_dynamic_a, super::longer_dynamic_b);
158
159 bench_all!([eq ne intern as_ref clone is_static lt]
160 for static_atom = test_atom!("a"), test_atom!("b"));
161
162 bench_all!([intern as_ref clone is_inline]
163 for short_inline_atom = mk("e"), mk("f"));
164
165 bench_all!([eq ne intern as_ref clone is_inline lt]
166 for medium_inline_atom = mk("xyzzy01"), mk("xyzzy02"));
167
168 bench_all!([intern as_ref clone is_dynamic]
169 for min_dynamic_atom = mk("xyzzy001"), mk("xyzzy002"));
170
171 bench_all!([eq ne intern as_ref clone is_dynamic lt]
172 for longer_dynamic_atom = mk(super::longer_dynamic_a), mk(super::longer_dynamic_b));
173
174 bench_all!([intern as_ref clone is_static]
175 for static_at_runtime = mk("a"), mk("b"));
176
177 bench_all!([ne lt x_static y_inline]
178 for static_vs_inline = test_atom!("a"), mk("f"));
179
180 bench_all!([ne lt x_static y_dynamic]
181 for static_vs_dynamic = test_atom!("a"), mk(super::longer_dynamic_b));
182
183 bench_all!([ne lt x_inline y_dynamic]
184 for inline_vs_dynamic = mk("e"), mk(super::longer_dynamic_b));
185
186 macro_rules! bench_rand ( ($name:ident, $len:expr) => (
187 #[bench]
188 fn $name(b: &mut Bencher) {
189 use std::str;
190 use rand;
191 use rand::Rng;
192
193 let mut gen = rand::weak_rng();
194 b.iter(|| {
195 // We have to generate new atoms on every iter, because
196 // the dynamic atom table isn't reset.
197 //
198 // I measured the overhead of random string generation
199 // as about 3-12% at one point.
200
201 let mut buf: [u8; $len] = [0; $len];
202 gen.fill_bytes(&mut buf);
203 for n in buf.iter_mut() {
204 // shift into printable ASCII
205 *n = (*n % 0x40) + 0x20;
206 }
207 let s = str::from_utf8(&buf[..]).unwrap();
208 black_box(TestAtom::from(s));
209 });
210 }
211 ));
212
213 bench_rand!(intern_rand_008, 8);
214 bench_rand!(intern_rand_032, 32);
215 bench_rand!(intern_rand_128, 128);
216 bench_rand!(intern_rand_512, 512);