From ba7bb2d6ad6e414dd567b2f4b959bd351de7cb75 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 17 Aug 2023 14:51:05 -0500 Subject: [PATCH] perf(token): Speed up `take_until` under simd This reverts commit 489aa2ace0ce77790cf8d2aa3fc0fcf8a8f7ccb2. PR #86 "FindSubstring<&[u8]>: make use of `memchr::memmem`" When testing under gitoxide, it turned out this slowed down gitoxide-specific micro-benchmarks from ~170ns to ~240ns --- src/stream/mod.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/stream/mod.rs b/src/stream/mod.rs index fcacbd78..5f2152e2 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -2684,7 +2684,35 @@ fn memchr(token: u8, slice: &[u8]) -> Option { #[cfg(feature = "simd")] #[inline(always)] fn memmem(slice: &[u8], tag: &[u8]) -> Option { - memchr::memmem::find(slice, tag) + if tag.len() > slice.len() { + return None; + } + + let (&substr_first, substr_rest) = match tag.split_first() { + Some(split) => split, + // an empty substring is found at position 0 + // This matches the behavior of str.find(""). + None => return Some(0), + }; + + if substr_rest.is_empty() { + return memchr::memchr(substr_first, slice); + } + + let mut offset = 0; + let haystack = &slice[..slice.len() - substr_rest.len()]; + + while let Some(position) = memchr::memchr(substr_first, &haystack[offset..]) { + offset += position; + let next_offset = offset + 1; + if &slice[next_offset..][..substr_rest.len()] == substr_rest { + return Some(offset); + } + + offset = next_offset; + } + + None } #[cfg(not(feature = "simd"))]