Xo 0.33 release notes
Downloads: Xo 0.33.0 on GitHub,
with archives for macOS (Apple silicon and Intel, signed and
notarized), Linux (arm64 and x86-64), and Windows (x86-64, Authenticode
signed), and a SHA256SUMS file.
This release makes rebuilding after an edit faster, brings the amd64 targets (Intel Macs, Linux and Windows on x86) to the arm64 targets’ edit speed, and brings AES-GCM and ChaCha20-Poly1305 on x86 to within about 1.3x of Go. Two small language changes: a newtype may derive Ord, and xo build skips inline test blocks.
Faster edit rebuilds
A one-function body edit with a warm cache, darwin/arm64, against 0.32.0 (20 interleaved runs):
| Program | 0.32.0 | 0.33.0 | |
|---|---|---|---|
| a small program (fib) | 333.5 ms | 244.5 ms | 27% faster |
| the HTTP CRUD server | 767.0 ms | 574.5 ms | 25% faster |
std/testingis loaded only when the program has test blocks; a program that imports nothing now checks about half as many std files.- The network runtime is built only into programs that use the network.
- Cache keys are chained from the front end’s entries (decision 0382), so an unchanged function skips more of the middle passes.
- The link’s cache key is computed from the objects’ cache keys, and the runtime’s hash is computed once.
xo buildandxo runskip inlinetestblocks (decision 0389), as they already skip_test.xofiles;xo checkandxo teststill check them.
amd64: Intel Macs, Linux and Windows on x86
- The per-function and per-part back-end cache now works on darwin/amd64, linux/amd64 and windows/amd64. An amd64 edit rebuild is within 15% of arm64’s on the same machine; an HTTP server edit on darwin/amd64 went from about 1.2 s to 0.64 s.
- The first edit after a cold build reuses cached parts (before, it reused none).
- Windows: compiled objects are cached and assembled in parallel. A native Windows HTTP server edit went from about 2.8 s to about 1.2 s. An edit built through the cache is byte for byte the same as a build with the cache off, checked on a native Windows Server host.
Crypto on x86
- AES-GCM processes eight blocks per round with AES-NI and PCLMULQDQ, after Go’s design.
- ChaCha20-Poly1305 has fused AVX2 and SSE kernels, with ChaCha20 and Poly1305 in one loop.
- Every SIMD path checks the CPU at run time and falls back to portable code; x86-64’s baseline is SSE2.
- Against Go 1.26.1 on an Intel Xeon Platinum 8488C (Xo time / Go time): AES-GCM seal and open 1.19 to 1.29, ChaCha20-Poly1305 seal 1.24 and open 1.27 (2.0 without AVX2), ChaCha20 alone 0.66.
- A differential test of 188 cases against Go, anchored to RFC 8439’s vectors, passes on the AVX2, SSE and portable paths.
Memory
- The allocator’s central free lists have one lock per size class (decision 0383): building the compiler itself peaks 0.75 GB lower, at no cost in time.
Standard library against Go
Xo time / Go time, before and after:
big: exp 12.75 to 0.92, mul 3.00 to 1.29, long division 1.95 to 1.42templaterender 2.92 to 1.86tomldecode 2.23 to about 1.58mimedetect 1.22 to 0.89;pathclean 1.15 to 1.02flateandgzip1.43 to 1.94, now 1.22 to 1.57uuidbytes 7.14 to 4.24- New Go comparisons for
compress,template,mail,archive,big,xml,tomlandwebsocket.
Language and std
- A newtype may
derive Ord(decision 0390):type Id struct(Str) derive Ordorders by the underlying value.min,maxandclampnow work on every derived-Ordtype in native builds. uuid.UuidderivesOrd(u < v, sorting). Readingu.0or building aUuidby hand outsidestd/uuidis deprecated:xo vetwarns XO0912 and namesdisplay(),parseand<(decision 0387). The representation changes in a later release.
Xo against Go
The released darwin/arm64 archive against Go 1.26.1, the same programs written in each (bench/perf’s Go twins), 10 interleaved rounds per workload under xo bench --ab (bench/results/release-vs-go-v0.33.0.md):
- Xo is faster on 17 of the 20 workloads and slower on 3: two-task ping-pong 1.20, parallel map 1.09 and n-body 1.05 (from 1.42 in 0.32.0). Fib, sieve and rwmutex moved from within noise to faster.
- Xo’s peak memory is lower on all 20 (0.38 to 0.97 of Go’s).
- Binaries are 1.60 to 1.71 MB against Go’s 2.39 to 2.43 MB.
- A one-function edit rebuild is 0.21 to 0.23 s against Go’s 0.10 to 0.11 s; separate compilation of the standard library (decision 0388) is the next release’s work on that gap.
Fixes
- Dead-code removal no longer keeps a function alive just because a safety-range marker sits in front of it (the compiler’s own binary shrank by 721 KB).