This patch significantly improves performance of memmem using a novel
modified Horspool algorithm. Needles up to size 256 use a bad-character
table indexed by hashed pairs of characters to quickly skip past mismatches.
Long needles use a self-adapting filtering step to avoid comparing the whole
needle repeatedly.
By limiting the needle length to 256, the shift table only requires 8 bits
per entry, lowering preprocessing overhead and minimizing cache effects.
This limit also implies worst-case performance is linear.
Small needles up to size 2 use a dedicated linear search. Very long needles
use the Two-Way algorithm (to avoid increasing stack size inlining is now disabled).
The performance gain is 6.6 times on English text on AArch64 using random
needles with average size 8 (this is even faster than the recently improved strstr
algorithm, so I'll update that in the near future).
The size-optimized memmem has also been rewritten from scratch to get a
2.7x performance gain.
Tested against GLIBC testsuite and randomized tests.
Message-Id: <DB5PR08MB1030649D051FA8532A4512C883B20@DB5PR08MB1030.eurprd08.prod.outlook.com>
* libc/string/str-two-way.h: New file.
* libc/string/memmem.c (memmem): New file.
* libc/include/string.h (memmem): Declare for all platforms.
* libc/string/strstr.c (strstr): Provide O(n) implementation when
not optimizing for space.
* libc/string/strcasestr.c (strcasestr): Likewise.
* libc/string/Makefile.am (ELIX_SOURCES): Rename to...
(ELIX_2_SOURCES): ...this.
(ELIX_4_SOURCES): New category, for memmem.
(lib_a_SOURCES, libstring_la_SOURCES): Build new file.
(CHEWOUT_FILES): Build documentation for memmem.
* libc/string/strings.tex: Include new docs.