Substring and Byte-Set Search Benchmarks

January 18, 2026 ยท View on GitHub

Benchmarks for substring search and character-set matching across Rust and Python implementations.

Substring search is one of the most common operations in text processing, and one of the slowest. Most of the time, programmers don't think about replacing the str::find method, as it's already expected to be optimized. In many languages it's offloaded to the C standard library memmem or strstr for NULL-terminated strings. The C standard library is, however, also implemented by humans, and a better solution can be created.

Forward Search (find)

LibraryShort Word QueriesLong Line Queries
Rust
std::str::find9.45 GB/s10.88 GB/s
memmem::find9.48 GB/s10.83 GB/s
memmem::Finder9.51 GB/s10.99 GB/s
stringzilla::find10.51 GB/s10.82 GB/s
Python
str.find1.05 GB/s1.23 GB/s
stringzilla.find10.82 GB/s11.79 GB/s

Reverse Search (rfind)

Interestingly, the reverse order search is almost never implemented in SIMD, assuming fewer people ever need it. Still, those are provided by StringZilla mostly for parsing tasks and feature parity.

LibraryShort Word QueriesLong Line Queries
Rust
std::str::rfind2.72 GB/s5.94 GB/s
memmem::rfind2.70 GB/s5.90 GB/s
memmem::FinderRev2.79 GB/s5.81 GB/s
stringzilla::rfind10.34 GB/s10.66 GB/s
Python
str.rfind1.54 GB/s3.84 GB/s
stringzilla.rfind7.15 GB/s11.56 GB/s

StringWars takes a few representative examples of various character sets that appear in real parsing or string validation tasks:

  • tabulation characters, like \n\r\v\f;
  • HTML and XML markup characters, like </>&'\"=[];
  • numeric characters, like 0123456789.

It's common in such cases, to pre-construct some library-specific filter-object or Finite State Machine (FSM) to search for a set of characters. Once that object is constructed, all of its inclusions in each token (word or line) are counted.

LibraryShort WordsLong Lines
Rust
bstr::iter0.26 GB/s0.25 GB/s
regex::find_iter0.23 GB/s5.22 GB/s
aho_corasick::find_iter0.41 GB/s0.50 GB/s
stringzilla::find_byteset1.61 GB/s8.17 GB/s
Python
re.finditer0.04 GB/s0.19 GB/s
stringzilla.Str.find_first_of0.11 GB/s8.79 GB/s

See README.md for dataset information and replication instructions.