Benchmarks
These benchmarks compare rapid-fuzzy with popular JavaScript libraries on the same data and queries. Run them on your own hardware in a clone of the repository with pnpm bench:readme, which rewrites the tables, then pnpm bench:charts, which redraws the charts from them; your data and queries matter more than these numbers. To try your own data in the browser, open the Playground, which times rapid-fuzzy, fuse.js and fuzzysort side by side.
Measured on 2026-10-04 with Node.js v22.22.0 on linux x64 (Intel(R) Xeon(R) Processor @ 2.10GHz, 4 logical CPUs, a shared cloud VM), using the release build of the native addon and Vitest bench. Numbers vary by up to about ±10% between runs; treat them as relative, not absolute.
How these numbers were produced (sources: __test__/search.compare.bench.ts, __test__/distance.compare.bench.ts and the datasets in __test__/bench-fixtures.ts; pnpm bench:readme re-runs them and rewrites these tables and the ones in the README):
- Datasets: 20 fruit names; 1,000 file paths such as
utils/config4.tsx; 10,000 to 100,000 generated identifiers such ashandler_repository_14. - Queries:
aple(20 items),utils config(1K),handler repo(10K-100K, matches 5% of the items). Every query matches items: a query that matches nothing measures an early exit, not a search. Rotating cycles through 8 different queries (ctrl,prms,service fac, …) so no search can reuse the previous one; type-ahead is one operation of 12 searches, one per keystroke ofhandler repo. - Settings: each library returns its top 5 (20 items) or 10 results; fuse.js uses
threshold: 0.4; fuzzysort usesthreshold: 0and, from 1K items on, prepared targets; uFuzzy uses its default options. - The libraries do not find the same matches, so the work they do differs: uFuzzy finds nothing for
aple, and fuse.js and uFuzzy find nothing for abbreviations such asctrlin the rotating set. FlexSearch and MiniSearch are token-based (FlexSearch finds nothing for most of these queries) and are left out. - Threads: on large inputs, the native addon spreads scoring over a thread pool (one thread per CPU, or
RAYON_NUM_THREADS); the JavaScript libraries use one thread. WithRAYON_NUM_THREADS=1,FuzzyIndexmeasured 1,004 ops/s on 50K items and 484 ops/s on 100K. The WASM build is single-threaded.
Search Performance
Section titled “Search Performance”Both
rapid-fuzzycolumns show the same library: standalonesearch()(converts the items on every call) and a prebuiltFuzzyIndex.
| Dataset | rapid-fuzzy | rapid-fuzzy (indexed) | fuse.js | fuzzysort | uFuzzy |
|---|---|---|---|---|---|
| Small (20 items) | 157,995 ops/s | 208,250 ops/s | 73,144 ops/s | 1,271,223 ops/s | 383,890 ops/s |
| Medium (1K items) | 3,502 ops/s | 50,318 ops/s | 249 ops/s | 54,110 ops/s | 16,858 ops/s |
| Large (10K items) | 508 ops/s | 4,803 ops/s | 27 ops/s | 2,977 ops/s | 1,404 ops/s |
| Large (10K items, rotating queries) | 451 ops/s | 4,644 ops/s | 32 ops/s | 2,231 ops/s | 1,037 ops/s |
| Large (10K items, type-ahead, 12 searches) | 42 ops/s | 555 ops/s | 4 ops/s | 271 ops/s | 62 ops/s |
| Extra large (50K items) | — | 2,120 ops/s | — | 631 ops/s | 755 ops/s |
| Huge (100K items) | — | 1,125 ops/s | — | 231 ops/s | 374 ops/s |
Closest Match
Section titled “Closest Match”closest() returns the best fuzzy-search match, while fastest-levenshtein’s closest() returns the item with the smallest edit distance, so the two can return different items (rapid-fuzzy returns null when no item contains the query’s characters in order). The queries below (utils/index42 and handler_repositry_514, one letter missing) make both return the same item. Both queries contain digits, which few items share, so the index’s character prefilter skips most items; less selective queries run at about the speed of the search table above.
| Dataset | rapid-fuzzy | rapid-fuzzy (indexed) | fastest-levenshtein |
|---|---|---|---|
| Medium (1K items) | 4,773 ops/s | 583,626 ops/s | 4,229 ops/s |
| Large (10K items) | 478 ops/s | 55,603 ops/s | 419 ops/s |
Distance Functions
Section titled “Distance Functions”Each operation computes 6 string pairs of varying length and similarity (6 to 45 characters).
| Function | rapid-fuzzy | fastest-levenshtein | leven | string-similarity |
|---|---|---|---|---|
| Levenshtein | 333,490 ops/s | 400,349 ops/s | 131,383 ops/s | — |
| Normalized Levenshtein | 325,462 ops/s | — | — | — |
| Sorensen-Dice | 178,705 ops/s | — | — | 56,320 ops/s |
| Jaro-Winkler | 299,960 ops/s | — | — | — |
| Damerau-Levenshtein | 87,724 ops/s | — | — | — |
| Hamming | 477,800 ops/s | — | — | — |
| Function | rapid-fuzzy | fuzzball |
|---|---|---|
| Token sort ratio | 209,369 ops/s | 51,588 ops/s |
| Token set ratio | 115,354 ops/s | 36,665 ops/s |
Weighted ratio (weightedRatio / WRatio) |
50,289 ops/s | 11,668 ops/s |
| Levenshtein, 1 vs 1,000 candidates | 3,752 ops/s (levenshteinMany) |
— |
| ↳ same, one call per candidate | 2,423 ops/s (levenshtein) |
fastest-levenshtein: 10,458 ops/s |
The token-based ratios do not return the same scores as fuzzball’s (see the fuzzball migration guide).
Key takeaways
Section titled “Key takeaways”- Indexed search: a
FuzzyIndexwas 10-14x faster per query than standalonesearch()on 1K-10K items, becausesearch()converts every item on every call. - vs fuse.js:
FuzzyIndexwas about 150-200x faster on 1K-10K items, and standalonesearch()about 14-19x. - vs fuzzysort: fuzzysort was faster on 20 items (about 6x) and about as fast on 1K items. On 10K items
FuzzyIndexwas 1.6-2.1x faster, and on 50K-100K items 3-5x faster using 4 threads (1.6-2.1x on one thread). - vs uFuzzy: uFuzzy was faster on 20 items;
FuzzyIndexwas about 3-4.5x faster on 1K-10K items. - Distance functions: for single pairs, fastest-levenshtein (pure JS) was about 1.2x faster than
levenshtein, and about 2.8x faster thanlevenshteinManyover 1,000 short candidates, since each call crosses the JS/Rust boundary. rapid-fuzzy was about 2.5x faster than leven, 3x faster than string-similarity and 3-4x faster than fuzzball’s ratios.