No description
  • Python 58.5%
  • Rust 41.5%
Find a file
2026-10-31 19:01:53 +00:00
grader tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
harness tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
ranks tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
sample tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
src Merge long pieces over token ids with a word-keyed heap, split where no token joins two bytes, and merge each part once a text 2026-10-31 19:01:53 +00:00
autoresearch.toml tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
Cargo.lock tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
Cargo.toml tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
compose.yaml tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
CONTRACT.md tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
dockerfile.grader tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
dockerfile.worker tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
LICENSE-tiktoken tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
PROGRAM.md tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00
README.md tiktoken: GPT-2 BPE encoding speed: the demo project 2026-10-24 00:00:00 +00:00

tiktoken-encode: GPT-2 BPE encoding speed

A timing project (PER-306): agents make tiktoken's Rust core (src/lib.rs, upstream's file) encode text faster with GPT-2's byte-pair encoding, and the grader times it on held-out documents it never shows, checking every token id against the reference's (wall_ms, minimized). Every improvement here is a patch upstream could take.

File What it is
autoresearch.toml the metric (wall_ms, minimized, MMI 15% relative), runner class cpu-s, editable src/**, K = 6; upstream openai/tiktoken, public
PROGRAM.md instructions for the agents: the encoder, the data, the budget, what counts as cheating
CONTRACT.md the worker HTTP contract (the template's, plus this project's items)
src/lib.rs the code being improved: tiktoken 0.14.0's Rust core, upstream's file verbatim to start with
Cargo.toml, Cargo.lock the workspace: the core's crates (fancy-regex, regex, rustc-hash, bstr) locked, the release profile
harness/worker.py the frozen HTTP server (Python's standard library): one encoder at startup, then each document's token ids hashed
harness/ffi/ the frozen C interface the server loads (bpe_new, bpe_encode, bpe_free): CoreBPE::new and encode_ordinary
ranks/gpt2.tiktoken GPT-2's BPE ranks, tiktoken's r50k_base
dockerfile.worker, compose.yaml Rust 1.99.1 builds the core and the interface; Python 3.13 serves them; worker on core 0, grader on core 1
dockerfile.grader, grader/ the grader (grade.py, standard library only) and the grader SDK (grader/arh_grader, sdk/grader verbatim)
sample/params.json the public sample: 9 timed and 2 warmup documents of three books, with the reference's answers
LICENSE-tiktoken tiktoken's MIT licence (src/lib.rs is its code)

The upstream

openai/tiktoken (MIT), release 0.14.0, commit 4e71bbe0c078468e00fefbf94b39849389f346e5: its Rust core src/lib.rs is this project's src/lib.rs unchanged; its Python bindings (src/py.rs, pyo3) are left out, and Cargo.toml is the project's (upstream's crates, its feature python declared but never enabled, a frozen release profile). Why tiktoken rather than Hugging Face's tokenizers (a large crate with a deep dependency tree) or GitHub's rust-gems/bpe (the fast one already: little room left): its core is one 702-line file, its own notes put most of the time in the pre-tokenizer regex, and the algorithmic headroom is on record (rust-gems/bpe reports about 10x over Hugging Face's).

The data

sdk/tiktoken/prepare.py in the platform's repository makes ranks/, sample/ and the held-out set from pinned files (each checked against its sha256), with tiktoken 0.14.0's encode_ordinary as the reference for every answer. The same files give the same bytes.

Source Licence Used for
GPT-2's encoder.json and vocab.bpe (openai-community/gpt2: vocab.json, merges.txt, byte for byte the files tiktoken's gpt2 encoding pins) MIT ranks/gpt2.tiktoken (equal to tiktoken's r50k_base)
Project Gutenberg: Pride and Prejudice (1342), Alice's Adventures in Wonderland (11), Le rouge et le noir (798) public domain in the US; the Project Gutenberg header and licence cut off sample/
Project Gutenberg: Moby Dick (2701), A Tale of Two Cities (98), The Adventures of Sherlock Holmes (1661), Dracula (345), Adventures of Huckleberry Finn (76), La Chartreuse de Parme (796), Faust (2229), Don Quijote (2000), 粉妝樓 (4572, 4573), お目出たき人 (31757), 羅生門 (1982), Λυσιστράτη (17814), Kalevala (7000), La Divina Commedia (1000), Os Lusíadas (3333), Московия в представлении иностранцев (30774), Robinsono Kruso (11511), Az arany szalamandra (18365), בית נכות ההלכות (43740) public domain in the US; header and licence cut off held-out: 55 pieces of books, fourteen languages
Django 5.1.2 (whole files) BSD-3-Clause held-out
SQLite 3.46.1's amalgamation (pieces) public domain (SQLite's blessing) held-out
serde_json 1.0.128 (whole files) MIT OR Apache-2.0 held-out
lodash 4.17.21 (pieces) MIT held-out
generated from seed 306: runs of one character, a word of random letters, scripts without spaces, emoji sequences, combining marks, control characters, whitespace runs, contractions, numbers, base64, hex, minified JSON, URLs, ligatures and full-width forms (23 documents) made here held-out

No code the worker's image or its build holds is held out: not Python's standard library (in the image) nor any crate of Cargo.lock (in the build), which the agents' core could read at startup and answer from a table. No Wikipedia text: its CC BY-SA share-alike terms aren't worth carrying for prose the books already cover. The held-out set (projects/tiktoken-encode-heldout/params.json, 98 timed and 2 warmup documents, 9.6 MB, 4.61 million tokens: 55 pieces of books, 22 of code, 23 generated) stays in the platform's repository and the graders' evaluation VMs; no image holds it (tests/projects/test_tiktoken_docker.py scans both).

How a run is scored

/eval/params.json (the held-out set on the platform; the public sample locally) holds the warmup documents, the timed ones and the reference's answer to each. The grader checks the set (the count expect says, documents of at most 200 KiB, answers of a digest and a count), sends the warmup documents untimed, then every timed document once, one a request, in an order drawn from the run's seed, and times each request. wall_ms is the total. Then it checks every answer: one that isn't the reference's (a token off changes the digest; a count off) is wrong, and any wrong or missing answer makes the run invalid. On the platform it then times the public sample the same way and reports it as public.

The baseline encodes the held-out set in about 1.8 s and the sample in about 140 ms (a shared lease's cores: 1806 and 1819 ms in two runs); in an eval VM on the dedicated timing core, about 2.0 to 2.2 s.

Noise and the MMI

A timing evaluation runs on the dedicated timing core (the r630's, PER-205). The MMI is twice the sd of the per-pair gain between two identical workers there, rounded up: 15% relative, and K = floor(0.9 / 0.15) = 6. It also meets PER-209's minimum (2 sigma_d).

Measured on 2026-10-31 with python -m arh_controller.characterize run (docs/noise.md): the baseline against itself on the held-out set (a copy of this directory with tiktoken-encode-heldout/params.json as its settings/heldout/, --setting heldout), --class cpu-s --nodes home-k8s-r630 --dedicated, 3 eval VMs of 10 A-B-B-A pairs each, one after another on the core (30 pairs, 60 runs; docs/noise/data/tiktoken-heldout-cpu-s-dedicated.json):

mean 2,181 ms (runs 1,990 to 2,795 ms)
sigma_d (relative) 7.29% (181 ms); per VM 7.6%, 3.8%, 9.0%
sd of the VMs' means 4.2%
MMI with 80% power for a 2-MMI gain (2/8 pairs, epsilon 0.05) 7.6%
the R630 meanwhile load1 33 of its 24 threads, CPU pressure 10.4%, IO pressure 5.8% (full 3.9%)

The noise is heavy-tailed: most pairs differ by 0 to 5%, but single runs come out 15 to 28% slow (2,795, 2,627 and 2,477 ms against about 2,050). FizzBuzz (3.2%) and a Python CPU loop (2.2%) are far quieter on the same core: the core is pinned, but its memory bandwidth and last-level cache are the busy host's, and this workload (ten megabytes of text, the ranks' hash map) leans on both. A quieter host (PER-328) could justify a smaller MMI, as a new reward version.

What the MMI must resolve is on record: the faster core in test_tiktoken_cluster.py (GPT-2's pattern through the regex crate, its lookahead done by hand) encodes the held-out set in about 1,150 ms against the baseline's 1,700 (three alternating runs each on the lease, every answer the reference's): a gain of about 32%, 2 MMIs.

The grader image

Built in a build VM by python -m arh_controller.grader_image projects/tiktoken-encode at commit 067358e, from grader/ at git tree e28d8e68b8fdfe373c056f846b239a3740076475, dockerfile.grader blob e3f181ae763e17064123e8d20d1ce096daa5840d and sample/ at git tree ea6cbd7ce807cea1aac153a7500255cf1e1ccd6c: archive digest sha256:55038f2d377f411b50507a77ec5d824b8a7b2194199abd517863917462d39fe8, image (config) id sha256:33cdedacf625ab2b49ff78d7c785e0ba6773e9b0541a1dcd52e5c73bc1f8290b, 134,177,280 bytes. It is the seeded reward version's grader_image_digest (arh_core.seed.TIKTOKEN); a change to any of those files needs a new build and a new reward version.

Running it

docker compose up --build --abort-on-container-exit --exit-code-from grader
docker compose run --rm --no-deps --entrypoint cat grader /result/result.json
docker compose down --volumes

compose.yaml pins the worker to core 0 and the grader to core 1, as runner class cpu-s places them. The first build downloads Rust's and Python's images and the locked crates from crates.io. arh run (the platform's CLI, cli/README.md) runs the same three commands and prints the result; its score is the public sample's, not the held-out set's.

Licences

What Source Licence
src/lib.rs openai/tiktoken 0.14.0, verbatim (LICENSE-tiktoken) MIT
ranks/gpt2.tiktoken GPT-2's vocabulary (openai-community/gpt2), as tiktoken writes it MIT
sample/ and the held-out set see "The data" public domain, BSD-3-Clause, MIT, MIT OR Apache-2.0, and ours
fancy-regex, regex, regex-automata, regex-syntax, aho-corasick, memchr, rustc-hash, bstr and their dependencies (Cargo.lock) crates.io, built into the worker's image, not vendored MIT OR Apache-2.0 (rustc-hash: Apache-2.0 OR MIT; memchr, aho-corasick also Unlicense)
Rust 1.99.1 (rust:1.99.1-slim-bookworm), Python 3.13 (python:3.13-slim-bookworm) Docker Hub, the images' bases MIT OR Apache-2.0; PSF-2.0