I benchmarked ~300 serializers across 14 languages, then built my own.
Kiln is a frozen, positional, little-endian wire format - and I wrote it
from scratch eleven times: Mojo, Go, Rust, Zig, C, C++, Python, Java,
Swift, C#, and TypeScript.
The one idea
JSON writes the names next to the values. Take a struct with two 32-bit
integers, x = 9 and y = -4:
- JSON:
{"x":9,"y":-4}- 14 bytes, names included. - Protocol Buffers: 13 bytes in this illustration, with a field number in
front of each value (and
-4widened to a 10-byte varint). - Kiln:
09 00 00 00 fc ff ff ff- 8 bytes. Just the two values, in declaration order, least significant byte first.
Both sides are built from the same struct, so each side already knows
which four bytes are x. The names stay in the source code, not on the
wire - and they are not written again on every copy of a batch, either.
The price, stated plainly
There is no name and no field number to jump over, so an unknown field
cannot be skipped. If the writer adds a third field, a reader built from
the two-field struct stops instead of guessing. That is the trade Kiln
makes on purpose, and version 2 of the spec writes its refusals down:
no per-field evolution tags, no columnar profile, no compression
wrapper, no dequantization, no GPU pointer. If you need those jobs,
other formats already do them well - Kiln refuses to pretend to be them.
What kept eleven implementations honest
One spec, and golden files. A Python reference codec writes the golden
files; every from-scratch codec is tested against them. That was the
only thing that could catch eleven independent implementations drifting
apart - and it is why the format is one format, not eleven similar ones.
Measured, not claimed
On an Intel i7-12800H (powersave governor, one pinned core, Mojo 1.1.0),
experiments/decode_small.mojo measured a 44-byte message at mean 15 ns
to encode and mean 28 ns to decode into owned strings. A batch of 100
messages encodes in mean 339 ns and decodes in mean 1.56 µs when UTF-8
is checked. The experiments page records the machine and the decisions.
Where to find it
- Spec + docs:
-
Flagship (Mojo):
- package
mojo-kilnon prefix.dev (linux-64), importkiln, generatorgld-kilngen-mojo
- package
- The other ten codecs: serialization, gld-kiln-go, gld-kiln-rust, gld-kiln-zig, gld-kiln-c, gld-kiln-cpp, gld-kiln-python, gld-kiln-java, gld-kiln-swift, gld-kiln-csharp, gld-kiln-typescript (all under github.com/leo-gan/)
If Kiln is useful to you, a star on the repo for the language you use
is the fastest way to help it grow. Feedback on the spec itself is
welcome - that is what a young format needs most.
Top comments (0)