A meta-issue tracking various ideas for SIMD-optimized string algorithms. A reason why we're making our own string APIs is because the C string library is made for null-terminated strings, which is quite useless when the major use case is working on slices of larger strings, such as in parsers. And (of course) the C++ counterparts are too bloated and either impose an implicit allocation or require a too new C++ standard.
SIMD in general
Construction
Searching
Comparison
Unicode
Number-to-string
For Utility::Debug, Utility::format() etc. The core should be a direct overhead-less API working on builtin types (writing into a statically-sized char[], e.g.), with convenience wrappers above.
String-to-number
Because strto*() has insane usability issues.
General printing
A meta-issue tracking various ideas for SIMD-optimized string algorithms. A reason why we're making our own string APIs is because the C string library is made for null-terminated strings, which is quite useless when the major use case is working on slices of larger strings, such as in parsers. And (of course) the C++ counterparts are too bloated and either impose an implicit allocation or require a too new C++ standard.
SIMD in general
Figure out how to dispatchhandled in Compile-time and runtime CPU feature (SIMD) detection and dispatch #115 as wellConstruction
Globalif it's a C string literal (using__constant_string_p()compiler builtin, details in constexpr StringView without literals #123)const char*asGlobalby checking if the pointer is in a read-only memory page -- https://github.com/RobloxResearch/SIMDString/blob/main/SIMDString.cpp#L54-L75Searching
memchr(),memchr2(),memchr3()etc., used infind(char),findAnyOf(),split()etc. for quickly skipping until end of line or end of a JSON string -- https://docs.rs/memchr/2.3.4/src/memchr/x86/avx.rs.htmlfindAnyNotOf()) when there's a lot of candidates andmemchr13()would be impossible to vectorize ("find the first that's not a space or newline and then decide what to do next")memrchr()and variants of above forfindLastAnyOf(). Linux has it, not sure where to look for a non-tainted implementation. At least we can benchmark against it as a black box.memmem()for faster generalfind()because of coursestrstr()is useless and I think we could do better thanmemcmp()in a loop. Linux has it, not sure where to look for a non-tainted implementation. At least we can benchmark against it as a black box.memrmem()forfindLast()std::boyer_moore_searcher(but this one needs a lot of preprocessing state)Arguments, plugin name, ... is mistyped --https://github.com/ninja-build/ninja/blob/ca041d88f4d610332aa48c801342edfafb622ccb/src/edit_distance.cc#L20-L69Comparison
memcmp()inStringView::operator==(), could save a lot especially when comparing literals that the compiler might have deduplicatedStringthomemcmp()ourselves?nullptrwhensize == 0just to not hit an UB because the standard is stupid and generally disallows passingnullptrto any string/memory function even if the size is zero?Any*plugins, OTOH there it's probably faster to normalize the extension first and then do 100memcmp()sUnicode
\uparsingaand¨as one), needs some Unicode categorization tableNumber-to-string
For
Utility::Debug,Utility::format()etc. The core should be a direct overhead-less API working on builtin types (writing into a statically-sizedchar[], e.g.), with convenience wrappers above.printf()-- even a dumbwhileloop would be betterprintf()to_charsused Ryu, not sure if it's still: https://twitter.com/StephanTLavavej/status/992881364142702593String-to-number
Because
strto*()has insane usability issues.strtol()-- even a dumbwhileloop could be better-for unsigned types (who thought that was a good idea??)strtof()/strtod()General printing