
Strings are the first fundamental data type every programming language implements in software rather than hardware, so dedicated CPU instructions are rare - and the few that exist are hardly ideal.
That's why most languages lean on the C standard library (libc) for their string operations, which, despite its name, ships its hottest code in hand-tuned assembly.
It does exploit SIMD, but it isn't perfect.
1️⃣ Even on ubiquitous hardware - over a billion 64-bit ARM CPUs - routines such as strstr and memmem top out at roughly one-third of available throughput.
2️⃣ SIMD coverage is uneven: fast forward scans don't guarantee speedy reverse searches, hashing and case-mapping is not even part of the standard.
3️⃣ Many higher-level languages can't rely on libc at all because their strings aren't NUL-terminated - or may even contain embedded zeroes.
That's why StringZilla exists: predictable, high performance on every modern platform, OS, and programming language.
StringZilla is the GodZilla of string libraries, using SIMD and SWAR to accelerate binary and UTF-8 string operations on modern CPUs and GPUs. It delivers up to 10x higher CPU throughput in C, C++, Rust, Python, and other languages, and can be 100x faster than existing GPU kernels, covering a broad range of functionality. It accelerates exact and fuzzy string matching, hashing, edit distance computations, sorting, provides allocation-free lazily-evaluated smart-iterators, and even random-string generators.
<string.h> to <stringzilla/stringzilla.h> in C 99<string> to <stringzilla/stringzilla.hpp> in C++ 11<stringzillas/stringzillas.cuh> in CUDA C++ 17str to faster StrStringZilla traits crateStringZilla cGo moduleString+StringZilla extensionStringZilla librarysz- prefixWho is this for?
LIKE, ORDER BY, and GROUP BY operations.| C | C++ | Python | StringZilla |
|---|---|---|---|
Unicode case-folding, expanding characters like ß → ss |
|||
| ⚪ | ⚪ |
.casefold
x86: 0.4 GB/s
|
sz.utf8_case_fold
x86: 1.3 GB/s
|
| Unicode case-insensitive substring search | |||
| ⚪ | ⚪ |
icu.StringSearch
x86: 0.02 GB/s
|
utf8_case_insensitive_find
x86: 3.0 GB/s
|
| find the first occurrence of a random word from text, ≅ 5 bytes long | |||
strstr 1
x86: 7.4 ·
arm: 2.0 GB/s
|
.find
x86: 2.9 ·
arm: 1.6 GB/s
|
.find
x86: 1.1 ·
arm: 0.6 GB/s
|
sz_find
x86: 10.6 ·
arm: 7.1 GB/s
|
| find the last occurrence of a random word from text, ≅ 5 bytes long | |||
| ⚪ |
.rfind
x86: 0.5 ·
arm: 0.4 GB/s
|
.rfind
x86: 0.9 ·
arm: 0.5 GB/s
|
sz_rfind
x86: 10.8 ·
arm: 6.7 GB/s
|
split lines separated by \n or \r 2 |
|||
strcspn 1
x86: 5.42 ·
arm: 2.19 GB/s
|
.find_first_of
x86: 0.59 ·
arm: 0.46 GB/s
|
re.finditer
x86: 0.06 ·
arm: 0.02 GB/s
|
sz_find_byteset
x86: 4.08 ·
arm: 3.22 GB/s
|
| find the last occurrence of any of 6 whitespaces 2 | |||
| ⚪ |
.find_last_of
x86: 0.25 ·
arm: 0.25 GB/s
|
⚪ |
sz_rfind_byteset
x86: 0.43 ·
arm: 0.23 GB/s
|
| Random string from a given alphabet, 20 bytes long 3 | |||
rand() % n
x86: 18.0 ·
arm: 9.4 MB/s
|
uniform_int_distribution
x86: 47.2 ·
arm: 20.4 MB/s
|
join(random.choices(x))
x86: 13.3 ·
arm: 5.9 MB/s
|
sz_fill_random
x86: 56.2 ·
arm: 25.8 MB/s
|
| Mapping characters with lookup table transforms | |||
| ⚪ |
std::transform
x86: 3.81 ·
arm: 2.65 GB/s
|
str.translate
x86: 260.0 ·
arm: 140.0 MB/s
|
sz_lookup
x86: 21.2 ·
arm: 8.5 GB/s
|
| Get sorted order, ≅ 8 million English words 4 | |||
qsort_r
x86: 3.55 ·
arm: 5.77 s
|
std::sort
x86: 2.79 ·
arm: 4.02 s
|
numpy.argsort
x86: 7.58 ·
arm: 13.00 s
|
sz_sequence_argsort
x86: 1.91 ·
arm: 2.37 s
|
| Levenshtein edit distance, text lines ≅ 100 bytes long | |||
| ⚪ | ⚪ |
via NLTK 5 and CuDF
x86: 1,615,306 ·
arm: 1,349,980 ·
cuda: 6,532,411,354 CUPS
|
szs_levenshtein_distances_t
x86: 3,434,427,548 ·
arm: 1,605,340,403 ·
cuda: 93,662,026,653 CUPS
|
| Needleman-Wunsch alignment scores, proteins ≅ 1 K amino acids long | |||
| ⚪ | ⚪ |
via biopython 6
x86: 575,981,513 ·
arm: 436,350,732 CUPS
|
szs_needleman_wunsch_scores_t
x86: 452,629,942 ·
arm: 520,170,239 · |
$ claude mcp add StringZilla \
-- python -m otcore.mcp_server <graph>