Tokenizer efficiency, actually measured
"Fewer tokens is cheaper" is true — but which tokenizer produces fewer tokens depends entirely on what you're tokenizing, and one popular way to measure it is quietly, dangerously wrong. This is an original benchmark of nine real tokenizers, run locally, fully reproducible, with the fidelity check most comparisons skip.
Across 9 tokenizers on English prose, all cluster near 4.5–5.2 characters per token — but the spread explodes on code and non-English text. On non-English (Hindi + Chinese), OpenAI's o200k_base encodes the same text in ~2.3 characters/token versus cl100k_base's ~1.0 — more than 2× fewer tokens, and 2× lower cost, for identical input. Critically, a naive "chars-per-token" ranking would crown T5 the most efficient on non-English text (3.4 chars/token) — but that number is an artifact: T5 silently drops ~48% of those characters to an unknown token because it cannot represent those scripts at all. Measuring efficiency without a fidelity check produces exactly this kind of confidently-wrong result.
Why token efficiency is worth measuring
You are billed per token, your context window is measured in tokens, and your latency scales with tokens. But a tokenizer doesn't turn text into tokens at a fixed rate — a "token" is a learned sub-word unit, and how many of them a given string becomes depends on how well that string matches the vocabulary the tokenizer was trained on. Two tokenizers handed the exact same document can differ by 2× or more in the token count they produce, which is a 2× difference in cost and context consumption for zero difference in input.
The usual way this gets summarized — "chars per token," higher is more efficient — is directionally right and hides a real trap that this benchmark is specifically built to expose.
Method — exactly what was measured
Nine production tokenizers were loaded and run against three corpora: a passage of English prose about the history of AI, a block of real Python code, and a passage of non-English text (Hindi and Chinese). For each tokenizer × corpus pair, three things were measured:
Characters per token — the corpus's character count divided by the token count it produced. Higher means fewer tokens for the same text, i.e. cheaper and more context-efficient. Encode throughput — best-of-20 wall-clock characters-per-second, to compare raw tokenization speed. Fidelity — the fraction of tokens that are the "unknown" token, and whether decode(encode(text)) reproduces the original's length. This last metric is the one that makes the benchmark honest.
| Tokenizer | Family | Vocab size |
|---|---|---|
| cl100k_base | OpenAI (tiktoken) — GPT-3.5/GPT-4 | 100,277 |
| o200k_base | OpenAI (tiktoken) — GPT-4o/GPT-5 family | 200,019 |
| gpt2 | OpenAI legacy byte-level BPE | 50,257 |
| Llama 2 | Meta — SentencePiece BPE | 32,000 |
| Qwen2.5 | Alibaba | 151,665 |
| DeepSeek-V3 | DeepSeek | 128,815 |
| bert-base-uncased | Google — WordPiece | 30,522 |
| t5-base | Google — SentencePiece Unigram | 32,100 |
| xlm-roberta-base | Meta — multilingual SentencePiece | 250,002 |
Bigger vocabularies can, in principle, encode text in fewer tokens (more sub-words to match against) — but only for text the vocabulary actually covers. XLM-RoBERTa's huge 250K vocab is spent on covering 100 languages; T5's tiny 32K vocab covers English well and most other scripts not at all. Vocab size alone predicts nothing without knowing what it was spent on.
Result 1 — English prose: everyone clusters
On ordinary English prose, all nine tokenizers land within a narrow band of roughly 4.5 to 5.2 characters per token. This is the case everyone's intuition is calibrated on, and it's the least interesting one — English is what every one of these tokenizers was most heavily trained on, so they all handle it competently.
If your workload is English text, the tokenizer barely matters for cost — the spread from best to worst here is about 14%, and every one of these is faithfully round-tripping the text. The interesting differences show up the moment you leave English prose.
Result 2 — code and non-English blow the spread wide open
Feed the same nine tokenizers Python code, and then non-English text, and the tight English cluster falls apart. GPT-2, the oldest tokenizer here, needs 2.3 characters per token on code — it fragments code into more than twice as many tokens as cl100k_base (4.21 c/t) does, because its older vocabulary never learned the common multi-character patterns of code. On non-English text the gaps get even larger, and this is where the fidelity check becomes essential.
| Tokenizer | Prose (c/t) | Code (c/t) | Non-English (c/t) | Non-English fidelity |
|---|---|---|---|---|
| cl100k_base | 5.20 | 4.21 | 1.04 | ✓ faithful |
| o200k_base | 5.17 | 4.19 | 2.28 | ✓ faithful |
| gpt2 | 5.20 | 2.30 | 0.59 | ✓ faithful |
| Llama 2 | 4.77 | 3.18 | 0.88 | ✓ faithful |
| Qwen2.5 | 5.13 | 4.16 | 1.29 | ✓ faithful |
| DeepSeek-V3 | 5.20 | 3.68 | 1.89 | ✓ faithful |
| bert-base-uncased | 5.09 | 3.83 | 1.37 | 36% UNK — lossy |
| t5-base | 4.82 | 3.15 | 3.39 | 48% UNK — lossy |
| xlm-roberta-base | 4.55 | 3.37 | 2.53 | ✓ faithful |
OpenAI's newer o200k_base (GPT-4o/GPT-5 family) encodes the non-English passage at 2.28 chars/token versus the older cl100k_base's 1.04 — more than 2× fewer tokens for identical text. If your workload has meaningful non-English content, the tokenizer generation directly halves your token cost on that content. This is a real, measured cross-generation improvement, not a marketing claim.
The trap — why "most efficient" can mean "silently broken"
Look at the non-English column again. By raw characters-per-token, T5 appears to be the single most efficient tokenizer on non-English text — 3.39 chars/token, comfortably ahead of everything else. A benchmark that stopped at chars-per-token would rank it first and publish that as a finding. It would be completely wrong.
The fidelity check tells the real story: 48% of T5's tokens on that text are the <unk> (unknown) token, and decode(encode(text)) reproduces only 17% of the original's length. T5's SentencePiece vocabulary was trained on English and simply cannot represent Hindi or Chinese characters — so instead of tokenizing them, it collapses whole runs of text into a single "I don't know this" token. That's why its token count is so low: it isn't efficiently encoding the text, it's throwing most of the text away. The impressive-looking 3.39 chars/token is the signature of data loss, not efficiency. BERT-base-uncased (English-only) shows a milder version of the same failure: 36% unknown tokens on the same input.
You cannot measure tokenizer efficiency by token count alone. A tokenizer that discards characters it can't represent will always look "more efficient" than one that faithfully encodes them — the exact opposite of the truth. Every honest tokenizer comparison needs a round-trip fidelity check, and most published ones don't have it. This is the single most important finding on this page.
Result 3 — encode speed: tiktoken is in a different league
Efficiency isn't only about token count — how fast a tokenizer runs matters for high-throughput pipelines that tokenize billions of characters. Here the split is stark and has a clear cause: OpenAI's tiktoken tokenizers (cl100k_base, o200k_base) are implemented in optimized Rust, while the HuggingFace-loaded tokenizers, though also Rust-backed, carry more per-call overhead in this setup. On English prose, o200k_base sustained ~32.7M characters/second and cl100k_base ~20.9M/s, while the rest clustered around 4–5M/s.
These throughput numbers reflect this specific machine (Apple Silicon, arm64) and library setup — treat the ~5–8× gap between tiktoken and the HF-loaded tokenizers as the durable finding, not the absolute megabytes-per-second, which will vary by hardware and library version. Token counts (results 1, 2, 5), by contrast, are deterministic properties of each tokenizer and reproduce exactly anywhere.
Reproduce it yourself
Every number on this page comes from the script below. The token counts are deterministic — you'll get the identical characters-per-token and identical unknown-token ratios on any machine. Only the speed numbers depend on your hardware. Install tiktoken and tokenizers, then run this against the same three corpora:
# pip install tiktoken tokenizers
# For each tokenizer, on each corpus, we measure:
# - token_count and chars_per_token (deterministic, reproduces anywhere)
# - unk_ratio: fraction of tokens that are the <unk> / [UNK] token
# - roundtrip_len_ratio: len(decode(encode(text))) / len(text)
# -> anything well below 1.0 means the tokenizer is DROPPING characters
# it can't represent, which inflates its apparent efficiency.
import tiktoken
from tokenizers import Tokenizer
def measure(encode, decode, unk_id, text):
ids = encode(text)
n = len(ids)
unk = ids.count(unk_id) if unk_id is not None else 0
decoded = decode(ids)
return {
"chars_per_token": len(text) / n,
"unk_ratio": unk / n,
"roundtrip_len_ratio": len(decoded) / len(text), # << the fidelity check
}
# tiktoken (byte-level BPE: no <unk>, always round-trips faithfully)
enc = tiktoken.get_encoding("o200k_base")
print(measure(lambda t: enc.encode(t, disallowed_special=()),
enc.decode, None, YOUR_TEXT))
# HuggingFace tokenizers (may have <unk>; CHECK roundtrip_len_ratio)
tok = Tokenizer.from_pretrained("t5-base")
unk = tok.token_to_id("<unk>")
print(measure(lambda t: tok.encode(t).ids, tok.decode, unk, YOUR_NON_ENGLISH_TEXT))
# -> t5-base on Hindi/Chinese: chars_per_token LOOKS great (~3.4),
# but unk_ratio ~0.48 and roundtrip_len_ratio ~0.17 expose that it is
# discarding ~half the text. Efficiency by token count alone is a lie here.Original data is only citable if it's checkable. The point of this page isn't the specific table — it's the reproducible method, and specifically the fidelity check that turns a misleading "T5 wins on non-English" into the correct "T5 can't represent non-English at all." Cite the finding, then run it yourself.
Quick answers
Which tokenizer is the most efficient?
It depends entirely on the text. On English prose all nine tested tokenizers are within ~14% of each other (4.5–5.2 chars/token). On non-English text, OpenAI’s o200k_base and Meta’s multilingual XLM-RoBERTa lead among the faithful tokenizers (~2.3–2.5 chars/token), while older or English-only tokenizers either fragment the text or can’t represent it at all.
Why does o200k_base beat cl100k_base on non-English text?
o200k_base is a newer OpenAI tokenizer (used by the GPT-4o and GPT-5 families) with a larger 200K vocabulary that covers non-English scripts far better. On the tested Hindi + Chinese passage it produced 2.28 chars/token versus cl100k_base’s 1.04 — more than 2× fewer tokens, and 2× lower cost, for identical input.
Can a tokenizer look efficient but actually be broken?
Yes — this is the central finding here. T5 appears most efficient on non-English text by raw chars-per-token (3.39), but 48% of those tokens are the unknown token and the text only 17% round-trips: T5 can’t represent those scripts and silently discards them. Measuring efficiency without a round-trip fidelity check produces confidently wrong rankings.
Are these token counts reproducible?
The token counts, characters-per-token, and unknown-token ratios are fully deterministic and reproduce exactly on any machine using the same tokenizer versions — the script and corpora are on this page. Only the encode-speed numbers depend on hardware, which is why the durable speed finding is stated as a ratio (tiktoken ~5–8× faster) rather than an absolute.
Go deeper
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Handbooks
- The Prompting HandbookA friendly, hands-on field guide for everyday humans — learn the CRISP framework, spot bad prompts, practice with real recipes, play a drag-and-drop game, and test yourself with a quiz. No code required.Read →
- The Agentic AI Interview HandbookTwenty topics every senior AI engineer should be able to reason about live — from eval pipelines to reliability patterns for generative systems.Read →
- The Senior AI Engineer Interview Handbook60 questions across architecture, production incidents, agentic systems, RAG, evals, cost, safety, and leadership — what staff-level AI interviewers actually probe for.Read →
- 50 Angular Interview QuestionsA visual handbook covering components, change detection, RxJS, signals, routing, forms, performance, and testing — what interviewers actually probe for in senior Angular roles.Read →
- 50 Python Interview QuestionsFundamentals to advanced: data structures, OOP, iterators & generators, the GIL, asyncio, memory, testing, and the standard library — a visual walk through everything a Python interview touches.Read →
- 51 LLM Evals Interview QuestionsGolden sets, LLM-as-judge, regression testing, offline vs online evals, RAG evals, agent evals, red-teaming, and observability — demystified for interviews and production.Read →
Explore more from Vibe Engines
Get the next one in your inbox.
New handbooks, system-design walkthroughs, and tools — straight to your inbox. No spam, unsubscribe anytime.