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