# Xo 0.33 release notes


**Downloads:** [Xo 0.33.0 on GitHub](https://github.com/xo-lang/xo/releases/tag/v0.33.0),
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/testing` is 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 build` and `xo run` skip inline `test` blocks (decision 0389), as they already skip `_test.xo` files; `xo check` and `xo test` still 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.42
- `template` render 2.92 to 1.86
- `toml` decode 2.23 to about 1.58
- `mime` detect 1.22 to 0.89; `path` clean 1.15 to 1.02
- `flate` and `gzip` 1.43 to 1.94, now 1.22 to 1.57
- `uuid` bytes 7.14 to 4.24
- New Go comparisons for `compress`, `template`, `mail`, `archive`, `big`, `xml`, `toml` and `websocket`.

## Language and std

- A newtype may `derive Ord` (decision 0390): `type Id struct(Str) derive Ord` orders by the underlying value. `min`, `max` and `clamp` now work on every derived-`Ord` type in native builds.
- `uuid.Uuid` derives `Ord` (`u < v`, sorting). Reading `u.0` or building a `Uuid` by hand outside `std/uuid` is deprecated: `xo vet` warns XO0912 and names `display()`, `parse` and `<` (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).

