Hugging Face ships tokenizers v1, up to 30x faster than v0.23

Hugging Face has published a release candidate of tokenizers v1, the next major version of its Rust tokenization library, and put it on crates.io for anyone to install with cargo add tokenizers --pre. The team's stated motivation is a bottleneck problem: as models get faster and workloads scale up, training on huge datasets, serving many concurrent requests, or repeatedly handling long inputs can put enough load on the tokenizer that GPUs sit idle waiting for the CPU to finish tokenizing. v1 is a performance-focused rewrite meant to remove that wait, while still producing the same token IDs, the same API, the same vocabulary and the same merge ranks as v0.23, so upgrading changes nothing about a model's output.
Three changes account for most of the speedup, all in the model stage of the tokenization pipeline, where byte pair encoding (BPE) turns pre-split text chunks into token IDs. First, the regular expression that normally splits raw text into pre-tokens is replaced, for a known set of grammars, by a hand-written splitter called bitcannon. Because that regex is a fixed, unchanging part of a given model, Hugging Face could write dedicated code for it instead of running a general-purpose regex engine on every encode call; bitcannon reads the input as parallel bit streams and finds boundaries with boolean operations across whole CPU registers, deciding 64 bytes per register operation. This only helps for tokenizers whose splitting pattern falls into one of the recognized grammars (the post names GPT-2, cl100k, o200k, Tekken and DeepSeek), which is why the reported speedups vary so much across models. Second, a thread-local word cache stores the token IDs already computed for a given pre-token's bytes, so repeated words in real text skip the merge process on later occurrences; the benefit grows as more of the input turns out to be repeated words, and shrinks for input with few repeats. Third, the BPE merge loop itself was redesigned: it now reuses a caller-owned scratch buffer instead of allocating memory and building a new priority queue on every call, stores symbols in a flat array linked by position, packs each candidate merge into a single 64-bit value so comparisons are pure integer comparisons, and processes a batch of pre-tokens per model call instead of one at a time.
Hugging Face benchmarked the release candidate, using its own tokbench repository, against other widely used tokenizer implementations across ten model families, covering single-threaded and multi-threaded performance, thread scaling, per-model and per-language comparisons, latency, decoding throughput, memory heap use and crate size. The headline result: on an Apple M4 Max, single-threaded, v1 encodes text 3 to 30 times faster than v0.23 across those ten families, with t5-base at the low end and gpt2 at the high end. Across eight worker threads it scales at 76% of linear, a separate measurement from the single-thread figure and not one to be combined with it. Eight of the ten benchmarked families use BPE; the other two use WordPiece and Unigram, the library's other supported model types.
The release candidate covers a defined slice of work: the workspace split into separate crates, the bitcannon splitter, the word cache, faster lookup and merge structures, reusable model memory, batched model calls and faster decoding are already in the Rust pre-release. Left for 1.0.0 are unifying training and inference around one encoding implementation, making offsets and masks optional and computed only on request, a normalizer rework, and simplified Python bindings, plus new inference-only C and C++ bindings for ExecuTorch and llama.cpp. No date is given for 1.0.0 beyond following once the release candidates stabilize. The post credits the broader tokenizer ecosystem, including gigatoken, tiktoken, kitoken, tokie, fastokens, wordchipper and ai-tokenizer, for ideas that fed into the rewrite, and thanks IBM, NVIDIA and the ExecuTorch team for contributing patches and testing across hardware. Training support is behind a default-on feature that pulls in a C++ dependency; anyone who only needs to encode can turn it off with cargo add tokenizers --pre --no-default-features --features http. The Python bindings call the same underlying code but add per-call overhead that the benchmarks in the post do not include.
Key facts
- Hugging Face put a release candidate of tokenizers v1 on crates.io, installable with cargo add tokenizers --pre.
- Single-threaded on an Apple M4 Max, v1 encodes text 3 to 30 times faster than v0.23 across the ten model families measured, from t5-base at the low end to gpt2 at the high end.
- Across eight worker threads, v1 scales at 76% of linear, a separate measurement from the single-thread speedup figure.
- Eight of the ten benchmarked model families use byte pair encoding (BPE); the other two use WordPiece and Unigram.
- The speedup comes from three changes to the model stage: a hand-written bitstream splitter (bitcannon) in place of a general regex engine, a thread-local word cache for repeated pre-tokens, and a merge loop that avoids per-call memory allocation, while v1 still produces exactly the same token IDs as v0.23.
Why it matters
Tokenization sits ahead of every model call, and Hugging Face frames v1 as fixing a bottleneck where fast GPUs end up idle waiting on the CPU to finish tokenizing, whether during training on large datasets, serving many concurrent requests, or repeatedly processing long inputs. v1 targets that gap directly: it reworks how the library splits text, caches repeated words and runs its merge loop, and reports single-threaded encode speedups of 3 to 30 times over v0.23 across ten model families, while keeping the output, API, vocabulary and merge ranks identical to the previous version.
Who it affects
Anyone building on the tokenizers Rust crate, and by extension the Python bindings and the transformers library that depend on it, since the post says improvements will be carried into that ecosystem once the release candidates stabilize. Hugging Face credits ideas from other open source tokenizer projects, gigatoken, tiktoken, kitoken, tokie, fastokens, wordchipper and ai-tokenizer, and thanks IBM, NVIDIA and the ExecuTorch team for contributing patches and testing across hardware to broaden platform support.
How to use it
The release candidate is on crates.io now: cargo add tokenizers --pre installs it, and the API is unchanged, so existing calls like tokenizer.encode and tokenizer.encode_batch work as before. Training support is behind a default-on feature that pulls in a C++ dependency; installing with cargo add tokenizers --pre --no-default-features --features http skips it for encode-only use. The Python bindings wrap the same Rust code but add per-call overhead that is not included in the benchmarks the post reports.
How solid is it
Hugging Face measured the release candidate against other widely used tokenizers using its own tokbench repository, which it says can be rerun on other hardware, across single-threaded and multi-threaded performance, thread scaling, per-model and per-language results, latency, decoding throughput, memory heap use and crate size. The stated single-thread result, 3 to 30 times faster than v0.23 across ten model families on an Apple M4 Max, and the 76% linear scaling across eight workers are two distinct measurements. The post states v1 still produces exactly the same token IDs as v0.23 throughout these changes.
Risks and caveats
The bitstream splitter only speeds up tokenizers whose splitting pattern matches a recognized grammar (the post names GPT-2, cl100k, o200k, Tekken and DeepSeek); a tokenizer outside that set keeps the older regex path and gets none of that particular speed-up, which the post gives as the reason the reported gains vary so widely. The word cache's benefit depends on how many repeated pre-tokens an input actually contains, so it helps less on input with few repeats. This is still a release candidate, not the final 1.0.0: unifying training and inference encoding, making offsets and masks optional, a normalizer rework and simplified Python bindings are all listed as still to come, and no date is given for when 1.0.0 itself will ship.