1fb6c1f39Sopenharmony_ci/*
2fb6c1f39Sopenharmony_ciThese benchmarks were lifted almost verbtaim out of the sliceslice crate. The
3fb6c1f39Sopenharmony_cireason why we have these benchmarks is because they were the primary thing that
4fb6c1f39Sopenharmony_cimotivated me to write this particular memmem implementation. In particular, my
5fb6c1f39Sopenharmony_ciexisting substring search implementation in the bstr crate did quite poorly
6fb6c1f39Sopenharmony_cion these particular benchmarks. Moreover, while the benchmark setup is a little
7fb6c1f39Sopenharmony_ciweird, these benchmarks do reflect cases that I think are somewhat common:
8fb6c1f39Sopenharmony_ci
9fb6c1f39Sopenharmony_ciN.B. In the sliceslice crate, the benchmarks are called "short" and "long."
10fb6c1f39Sopenharmony_ciHere, we call them sliceslice-words/words and sliceslice-i386/words,
11fb6c1f39Sopenharmony_cirespectively. The name change was made to be consistent with the naming
12fb6c1f39Sopenharmony_ciconvention used for other benchmarks.
13fb6c1f39Sopenharmony_ci
14fb6c1f39Sopenharmony_ci* In the sliceslice-words/words case, the benchmark is primarily about
15fb6c1f39Sopenharmony_ci  searching very short haystacks using common English words.
16fb6c1f39Sopenharmony_ci* In the sliceslice-words/i386 case, the benchmark is primarily about searching
17fb6c1f39Sopenharmony_ci  a longer haystack with common English words.
18fb6c1f39Sopenharmony_ci
19fb6c1f39Sopenharmony_ciThe main thing that's "weird" about these benchmarks is that each iteration
20fb6c1f39Sopenharmony_ciinvolves a lot of work. All of the other benchmarks in this crate focus on one
21fb6c1f39Sopenharmony_cispecific needle with one specific haystack, and each iteration is a single
22fb6c1f39Sopenharmony_cisearch or iteration. But in these benchmarks, each iteration involves searching
23fb6c1f39Sopenharmony_ciwith many needles against potentially many haystacks. Nevertheless, these have
24fb6c1f39Sopenharmony_ciproven useful targets for optimization.
25fb6c1f39Sopenharmony_ci*/
26fb6c1f39Sopenharmony_ciuse criterion::{black_box, Criterion};
27fb6c1f39Sopenharmony_ciuse memchr::memmem;
28fb6c1f39Sopenharmony_ci
29fb6c1f39Sopenharmony_ciuse crate::{data::*, define};
30fb6c1f39Sopenharmony_ci
31fb6c1f39Sopenharmony_cipub fn all(c: &mut Criterion) {
32fb6c1f39Sopenharmony_ci    search_short_haystack(c);
33fb6c1f39Sopenharmony_ci    search_long_haystack(c);
34fb6c1f39Sopenharmony_ci    search_i386_haystack(c);
35fb6c1f39Sopenharmony_ci}
36fb6c1f39Sopenharmony_ci
37fb6c1f39Sopenharmony_cifn search_short_haystack(c: &mut Criterion) {
38fb6c1f39Sopenharmony_ci    let mut words = SLICESLICE_WORDS.lines().collect::<Vec<_>>();
39fb6c1f39Sopenharmony_ci    words.sort_unstable_by_key(|word| word.len());
40fb6c1f39Sopenharmony_ci    let words: Vec<&str> = words.iter().map(|&s| s).collect();
41fb6c1f39Sopenharmony_ci
42fb6c1f39Sopenharmony_ci    let needles = words.clone();
43fb6c1f39Sopenharmony_ci    define(
44fb6c1f39Sopenharmony_ci        c,
45fb6c1f39Sopenharmony_ci        "memmem/krate/prebuilt/sliceslice-words/words",
46fb6c1f39Sopenharmony_ci        &[],
47fb6c1f39Sopenharmony_ci        Box::new(move |b| {
48fb6c1f39Sopenharmony_ci            let searchers = needles
49fb6c1f39Sopenharmony_ci                .iter()
50fb6c1f39Sopenharmony_ci                .map(|needle| memmem::Finder::new(needle.as_bytes()))
51fb6c1f39Sopenharmony_ci                .collect::<Vec<_>>();
52fb6c1f39Sopenharmony_ci            b.iter(|| {
53fb6c1f39Sopenharmony_ci                for (i, searcher) in searchers.iter().enumerate() {
54fb6c1f39Sopenharmony_ci                    for haystack in &needles[i..] {
55fb6c1f39Sopenharmony_ci                        black_box(
56fb6c1f39Sopenharmony_ci                            searcher.find(haystack.as_bytes()).is_some(),
57fb6c1f39Sopenharmony_ci                        );
58fb6c1f39Sopenharmony_ci                    }
59fb6c1f39Sopenharmony_ci                }
60fb6c1f39Sopenharmony_ci            });
61fb6c1f39Sopenharmony_ci        }),
62fb6c1f39Sopenharmony_ci    );
63fb6c1f39Sopenharmony_ci
64fb6c1f39Sopenharmony_ci    let needles = words.clone();
65fb6c1f39Sopenharmony_ci    define(
66fb6c1f39Sopenharmony_ci        c,
67fb6c1f39Sopenharmony_ci        "memmem/krate_nopre/prebuilt/sliceslice-words/words",
68fb6c1f39Sopenharmony_ci        &[],
69fb6c1f39Sopenharmony_ci        Box::new(move |b| {
70fb6c1f39Sopenharmony_ci            let searchers = needles
71fb6c1f39Sopenharmony_ci                .iter()
72fb6c1f39Sopenharmony_ci                .map(|needle| {
73fb6c1f39Sopenharmony_ci                    memmem::FinderBuilder::new()
74fb6c1f39Sopenharmony_ci                        .prefilter(memmem::Prefilter::None)
75fb6c1f39Sopenharmony_ci                        .build_forward(needle)
76fb6c1f39Sopenharmony_ci                })
77fb6c1f39Sopenharmony_ci                .collect::<Vec<_>>();
78fb6c1f39Sopenharmony_ci            b.iter(|| {
79fb6c1f39Sopenharmony_ci                for (i, searcher) in searchers.iter().enumerate() {
80fb6c1f39Sopenharmony_ci                    for haystack in &needles[i..] {
81fb6c1f39Sopenharmony_ci                        black_box(
82fb6c1f39Sopenharmony_ci                            searcher.find(haystack.as_bytes()).is_some(),
83fb6c1f39Sopenharmony_ci                        );
84fb6c1f39Sopenharmony_ci                    }
85fb6c1f39Sopenharmony_ci                }
86fb6c1f39Sopenharmony_ci            });
87fb6c1f39Sopenharmony_ci        }),
88fb6c1f39Sopenharmony_ci    );
89fb6c1f39Sopenharmony_ci
90fb6c1f39Sopenharmony_ci    let needles = words.clone();
91fb6c1f39Sopenharmony_ci    define(
92fb6c1f39Sopenharmony_ci        c,
93fb6c1f39Sopenharmony_ci        "memmem/stud/prebuilt/sliceslice-words/words",
94fb6c1f39Sopenharmony_ci        &[],
95fb6c1f39Sopenharmony_ci        Box::new(move |b| {
96fb6c1f39Sopenharmony_ci            b.iter(|| {
97fb6c1f39Sopenharmony_ci                for (i, needle) in needles.iter().enumerate() {
98fb6c1f39Sopenharmony_ci                    for haystack in &needles[i..] {
99fb6c1f39Sopenharmony_ci                        black_box(haystack.contains(needle));
100fb6c1f39Sopenharmony_ci                    }
101fb6c1f39Sopenharmony_ci                }
102fb6c1f39Sopenharmony_ci            });
103fb6c1f39Sopenharmony_ci        }),
104fb6c1f39Sopenharmony_ci    );
105fb6c1f39Sopenharmony_ci
106fb6c1f39Sopenharmony_ci    #[cfg(target_arch = "x86_64")]
107fb6c1f39Sopenharmony_ci    {
108fb6c1f39Sopenharmony_ci        use sliceslice::x86::DynamicAvx2Searcher;
109fb6c1f39Sopenharmony_ci
110fb6c1f39Sopenharmony_ci        let needles = words.clone();
111fb6c1f39Sopenharmony_ci        define(
112fb6c1f39Sopenharmony_ci            c,
113fb6c1f39Sopenharmony_ci            "memmem/sliceslice/prebuilt/sliceslice-words/words",
114fb6c1f39Sopenharmony_ci            &[],
115fb6c1f39Sopenharmony_ci            Box::new(move |b| {
116fb6c1f39Sopenharmony_ci                let searchers = needles
117fb6c1f39Sopenharmony_ci                    .iter()
118fb6c1f39Sopenharmony_ci                    .map(|&needle| unsafe {
119fb6c1f39Sopenharmony_ci                        DynamicAvx2Searcher::new(needle.as_bytes())
120fb6c1f39Sopenharmony_ci                    })
121fb6c1f39Sopenharmony_ci                    .collect::<Vec<_>>();
122fb6c1f39Sopenharmony_ci
123fb6c1f39Sopenharmony_ci                b.iter(|| {
124fb6c1f39Sopenharmony_ci                    for (i, searcher) in searchers.iter().enumerate() {
125fb6c1f39Sopenharmony_ci                        for haystack in &needles[i..] {
126fb6c1f39Sopenharmony_ci                            black_box(unsafe {
127fb6c1f39Sopenharmony_ci                                searcher.search_in(haystack.as_bytes())
128fb6c1f39Sopenharmony_ci                            });
129fb6c1f39Sopenharmony_ci                        }
130fb6c1f39Sopenharmony_ci                    }
131fb6c1f39Sopenharmony_ci                });
132fb6c1f39Sopenharmony_ci            }),
133fb6c1f39Sopenharmony_ci        );
134fb6c1f39Sopenharmony_ci    }
135fb6c1f39Sopenharmony_ci}
136fb6c1f39Sopenharmony_ci
137fb6c1f39Sopenharmony_cifn search_long_haystack(c: &mut Criterion) {
138fb6c1f39Sopenharmony_ci    let words: Vec<&str> = SLICESLICE_WORDS.lines().collect();
139fb6c1f39Sopenharmony_ci    let haystack = SLICESLICE_HAYSTACK;
140fb6c1f39Sopenharmony_ci    let needles = words.clone();
141fb6c1f39Sopenharmony_ci    define(
142fb6c1f39Sopenharmony_ci        c,
143fb6c1f39Sopenharmony_ci        "memmem/krate/prebuilt/sliceslice-haystack/words",
144fb6c1f39Sopenharmony_ci        &[],
145fb6c1f39Sopenharmony_ci        Box::new(move |b| {
146fb6c1f39Sopenharmony_ci            let searchers = needles
147fb6c1f39Sopenharmony_ci                .iter()
148fb6c1f39Sopenharmony_ci                .map(|needle| memmem::Finder::new(needle.as_bytes()))
149fb6c1f39Sopenharmony_ci                .collect::<Vec<_>>();
150fb6c1f39Sopenharmony_ci            b.iter(|| {
151fb6c1f39Sopenharmony_ci                for searcher in searchers.iter() {
152fb6c1f39Sopenharmony_ci                    black_box(searcher.find(haystack.as_bytes()).is_some());
153fb6c1f39Sopenharmony_ci                }
154fb6c1f39Sopenharmony_ci            });
155fb6c1f39Sopenharmony_ci        }),
156fb6c1f39Sopenharmony_ci    );
157fb6c1f39Sopenharmony_ci
158fb6c1f39Sopenharmony_ci    let needles = words.clone();
159fb6c1f39Sopenharmony_ci    define(
160fb6c1f39Sopenharmony_ci        c,
161fb6c1f39Sopenharmony_ci        "memmem/krate_nopre/prebuilt/sliceslice-haystack/words",
162fb6c1f39Sopenharmony_ci        &[],
163fb6c1f39Sopenharmony_ci        Box::new(move |b| {
164fb6c1f39Sopenharmony_ci            let searchers = needles
165fb6c1f39Sopenharmony_ci                .iter()
166fb6c1f39Sopenharmony_ci                .map(|needle| {
167fb6c1f39Sopenharmony_ci                    memmem::FinderBuilder::new()
168fb6c1f39Sopenharmony_ci                        .prefilter(memmem::Prefilter::None)
169fb6c1f39Sopenharmony_ci                        .build_forward(needle)
170fb6c1f39Sopenharmony_ci                })
171fb6c1f39Sopenharmony_ci                .collect::<Vec<_>>();
172fb6c1f39Sopenharmony_ci            b.iter(|| {
173fb6c1f39Sopenharmony_ci                for searcher in searchers.iter() {
174fb6c1f39Sopenharmony_ci                    black_box(searcher.find(haystack.as_bytes()).is_some());
175fb6c1f39Sopenharmony_ci                }
176fb6c1f39Sopenharmony_ci            });
177fb6c1f39Sopenharmony_ci        }),
178fb6c1f39Sopenharmony_ci    );
179fb6c1f39Sopenharmony_ci
180fb6c1f39Sopenharmony_ci    let needles = words.clone();
181fb6c1f39Sopenharmony_ci    define(
182fb6c1f39Sopenharmony_ci        c,
183fb6c1f39Sopenharmony_ci        "memmem/stud/prebuilt/sliceslice-haystack/words",
184fb6c1f39Sopenharmony_ci        &[],
185fb6c1f39Sopenharmony_ci        Box::new(move |b| {
186fb6c1f39Sopenharmony_ci            b.iter(|| {
187fb6c1f39Sopenharmony_ci                for needle in needles.iter() {
188fb6c1f39Sopenharmony_ci                    black_box(haystack.contains(needle));
189fb6c1f39Sopenharmony_ci                }
190fb6c1f39Sopenharmony_ci            });
191fb6c1f39Sopenharmony_ci        }),
192fb6c1f39Sopenharmony_ci    );
193fb6c1f39Sopenharmony_ci
194fb6c1f39Sopenharmony_ci    #[cfg(target_arch = "x86_64")]
195fb6c1f39Sopenharmony_ci    {
196fb6c1f39Sopenharmony_ci        use sliceslice::x86::DynamicAvx2Searcher;
197fb6c1f39Sopenharmony_ci
198fb6c1f39Sopenharmony_ci        let needles = words.clone();
199fb6c1f39Sopenharmony_ci        define(
200fb6c1f39Sopenharmony_ci            c,
201fb6c1f39Sopenharmony_ci            "memmem/sliceslice/prebuilt/sliceslice-haystack/words",
202fb6c1f39Sopenharmony_ci            &[],
203fb6c1f39Sopenharmony_ci            Box::new(move |b| {
204fb6c1f39Sopenharmony_ci                let searchers = needles
205fb6c1f39Sopenharmony_ci                    .iter()
206fb6c1f39Sopenharmony_ci                    .map(|needle| unsafe {
207fb6c1f39Sopenharmony_ci                        DynamicAvx2Searcher::new(needle.as_bytes())
208fb6c1f39Sopenharmony_ci                    })
209fb6c1f39Sopenharmony_ci                    .collect::<Vec<_>>();
210fb6c1f39Sopenharmony_ci
211fb6c1f39Sopenharmony_ci                b.iter(|| {
212fb6c1f39Sopenharmony_ci                    for searcher in &searchers {
213fb6c1f39Sopenharmony_ci                        black_box(unsafe {
214fb6c1f39Sopenharmony_ci                            searcher.search_in(haystack.as_bytes())
215fb6c1f39Sopenharmony_ci                        });
216fb6c1f39Sopenharmony_ci                    }
217fb6c1f39Sopenharmony_ci                });
218fb6c1f39Sopenharmony_ci            }),
219fb6c1f39Sopenharmony_ci        );
220fb6c1f39Sopenharmony_ci    }
221fb6c1f39Sopenharmony_ci}
222fb6c1f39Sopenharmony_ci
223fb6c1f39Sopenharmony_cifn search_i386_haystack(c: &mut Criterion) {
224fb6c1f39Sopenharmony_ci    let words: Vec<&str> = SLICESLICE_WORDS.lines().collect();
225fb6c1f39Sopenharmony_ci    let haystack = SLICESLICE_I386;
226fb6c1f39Sopenharmony_ci    let needles = words.clone();
227fb6c1f39Sopenharmony_ci    define(
228fb6c1f39Sopenharmony_ci        c,
229fb6c1f39Sopenharmony_ci        "memmem/krate/prebuilt/sliceslice-i386/words",
230fb6c1f39Sopenharmony_ci        &[],
231fb6c1f39Sopenharmony_ci        Box::new(move |b| {
232fb6c1f39Sopenharmony_ci            let searchers = needles
233fb6c1f39Sopenharmony_ci                .iter()
234fb6c1f39Sopenharmony_ci                .map(|needle| memmem::Finder::new(needle.as_bytes()))
235fb6c1f39Sopenharmony_ci                .collect::<Vec<_>>();
236fb6c1f39Sopenharmony_ci            b.iter(|| {
237fb6c1f39Sopenharmony_ci                for searcher in searchers.iter() {
238fb6c1f39Sopenharmony_ci                    black_box(searcher.find(haystack.as_bytes()).is_some());
239fb6c1f39Sopenharmony_ci                }
240fb6c1f39Sopenharmony_ci            });
241fb6c1f39Sopenharmony_ci        }),
242fb6c1f39Sopenharmony_ci    );
243fb6c1f39Sopenharmony_ci
244fb6c1f39Sopenharmony_ci    let needles = words.clone();
245fb6c1f39Sopenharmony_ci    define(
246fb6c1f39Sopenharmony_ci        c,
247fb6c1f39Sopenharmony_ci        "memmem/krate_nopre/prebuilt/sliceslice-i386/words",
248fb6c1f39Sopenharmony_ci        &[],
249fb6c1f39Sopenharmony_ci        Box::new(move |b| {
250fb6c1f39Sopenharmony_ci            let searchers = needles
251fb6c1f39Sopenharmony_ci                .iter()
252fb6c1f39Sopenharmony_ci                .map(|needle| {
253fb6c1f39Sopenharmony_ci                    memmem::FinderBuilder::new()
254fb6c1f39Sopenharmony_ci                        .prefilter(memmem::Prefilter::None)
255fb6c1f39Sopenharmony_ci                        .build_forward(needle)
256fb6c1f39Sopenharmony_ci                })
257fb6c1f39Sopenharmony_ci                .collect::<Vec<_>>();
258fb6c1f39Sopenharmony_ci            b.iter(|| {
259fb6c1f39Sopenharmony_ci                for searcher in searchers.iter() {
260fb6c1f39Sopenharmony_ci                    black_box(searcher.find(haystack.as_bytes()).is_some());
261fb6c1f39Sopenharmony_ci                }
262fb6c1f39Sopenharmony_ci            });
263fb6c1f39Sopenharmony_ci        }),
264fb6c1f39Sopenharmony_ci    );
265fb6c1f39Sopenharmony_ci
266fb6c1f39Sopenharmony_ci    let needles = words.clone();
267fb6c1f39Sopenharmony_ci    define(
268fb6c1f39Sopenharmony_ci        c,
269fb6c1f39Sopenharmony_ci        "memmem/stud/prebuilt/sliceslice-i386/words",
270fb6c1f39Sopenharmony_ci        &[],
271fb6c1f39Sopenharmony_ci        Box::new(move |b| {
272fb6c1f39Sopenharmony_ci            b.iter(|| {
273fb6c1f39Sopenharmony_ci                for needle in needles.iter() {
274fb6c1f39Sopenharmony_ci                    black_box(haystack.contains(needle));
275fb6c1f39Sopenharmony_ci                }
276fb6c1f39Sopenharmony_ci            });
277fb6c1f39Sopenharmony_ci        }),
278fb6c1f39Sopenharmony_ci    );
279fb6c1f39Sopenharmony_ci
280fb6c1f39Sopenharmony_ci    #[cfg(target_arch = "x86_64")]
281fb6c1f39Sopenharmony_ci    {
282fb6c1f39Sopenharmony_ci        use sliceslice::x86::DynamicAvx2Searcher;
283fb6c1f39Sopenharmony_ci
284fb6c1f39Sopenharmony_ci        let needles = words.clone();
285fb6c1f39Sopenharmony_ci        define(
286fb6c1f39Sopenharmony_ci            c,
287fb6c1f39Sopenharmony_ci            "memmem/sliceslice/prebuilt/sliceslice-i386/words",
288fb6c1f39Sopenharmony_ci            &[],
289fb6c1f39Sopenharmony_ci            Box::new(move |b| {
290fb6c1f39Sopenharmony_ci                let searchers = needles
291fb6c1f39Sopenharmony_ci                    .iter()
292fb6c1f39Sopenharmony_ci                    .map(|needle| unsafe {
293fb6c1f39Sopenharmony_ci                        DynamicAvx2Searcher::new(needle.as_bytes())
294fb6c1f39Sopenharmony_ci                    })
295fb6c1f39Sopenharmony_ci                    .collect::<Vec<_>>();
296fb6c1f39Sopenharmony_ci
297fb6c1f39Sopenharmony_ci                b.iter(|| {
298fb6c1f39Sopenharmony_ci                    for searcher in &searchers {
299fb6c1f39Sopenharmony_ci                        black_box(unsafe {
300fb6c1f39Sopenharmony_ci                            searcher.search_in(haystack.as_bytes())
301fb6c1f39Sopenharmony_ci                        });
302fb6c1f39Sopenharmony_ci                    }
303fb6c1f39Sopenharmony_ci                });
304fb6c1f39Sopenharmony_ci            }),
305fb6c1f39Sopenharmony_ci        );
306fb6c1f39Sopenharmony_ci    }
307fb6c1f39Sopenharmony_ci}
308