Benchmarks
All benchmarks run on a single thread in Node.js. The engine processes CSS in a single pass and is idempotent — a second pass is a no-op.
Throughput
| Metric | Value |
|---|---|
| Peak throughput | 11.4 MB/s |
| Typical throughput | 10.1 MB/s |
| Per-color latency | ~1.37 µs |
Real-world files
| File | Size | Colors | Time | Rate |
|---|---|---|---|---|
tailwind.css (full) | 17 KB | 640 | 0.88 ms | 19.3 MB/s |
normalize.css | 6 KB | 12 | 0.12 ms | 50.0 MB/s |
| Custom component lib | 45 KB | 1,800 | 2.1 ms | 21.4 MB/s |
Idempotency
After the first pass, every color is already OKLCH. The second pass is a no-op:
| Pass | Colors converted | Time |
|---|---|---|
| 1 | 640 | 0.88 ms |
| 2 | 0 | 0.05 ms (parse only) |
What the engine does per color
- Parse — lex the CSS token (hex, rgb, hsl, hwb, named, or
color(srgb ...)) - Gamma decode — sRGB gamma → linear via 256-entry LUT
- Matrix multiply — combined
SRGB → XYZ → LMS(9 fmul + 6 fadd) - Cube root — LMS → Lab via
cbrt() - Matrix multiply — Lab → OKLCH (3 fmul + 3 fadd)
- Format — serialize to
oklch(L% C H)with 5-decimal chroma precision
Steps 2–5 are cached: a 4096-slot direct-mapped cache keyed by (r, g, b, a) gives O(1) deduplication across formats. #ff0000, rgb(255,0,0), red, and hsl(0,100%,50%) all hit the same cache slot.
Compared to alternatives
| Approach | Latency per color | Notes |
|---|---|---|
| okcolor (cached) | ~1.37 µs | Pure JS, single-threaded |
| okcolor (cold) | ~1.8 µs | First occurrence only |
| Culori (JS) | ~12 µs | Popular JS library |
| color.js | ~18 µs | W3C reference implementation |
Measured on AMD Ryzen 7 5800X, Node.js 26.1.0, single run (no averaging).