Skip to content

Zig

Zig is in this suite because comptime reflection (@typeInfo) is a different implementation model from Java/Kotlin runtime reflection, C# source generation, or Rust derive macros. The runner times official std.json (typed parseFromSlice versus streaming Scanner / parseFromTokenSource) against an in-tree comptime byte-packed baseline, against serde.zig, a format-agnostic framework that uses the same @typeInfo walk for JSON, MessagePack, YAML, TOML, and ZON, and against schema codecs (Protocol Buffers, FlatBuffers, Cap’n Proto) generated from the shared suite IDLs.

Runtime

What it is

Zig compiles to native machine code. There is no hidden virtual machine and no garbage collector. Allocation is explicit: the benchmark runner passes allocators in. Comptime means the compiler can run Zig code while it builds. @typeInfo walks a struct at compile time instead of using Java-style reflection at run time.

This suite
Compiler Zig 0.16.x. Version 0.15 or 0.17 will not build this tree.
Prepare ./scripts/install-host-requirements.sh zig installs into ~/.local/zig
Run zig/scripts/run-benchmarks.sh (zig build)
Memory Explicit allocators. No garbage collector.

What this suite runs

Zig still changes in breaking ways between minor versions, so the host script installs 0.16.x and the checker rejects any other series. The Zig binary does not start Python. Cap’n Proto uses the official C++ library, because Zig 0.16 has no native Cap’n Proto plugin.

What changes the numbers

Building without optimizations is the error that changes the numbers the most, because an unoptimized Zig binary is far slower than a release build. Codecs that use comptime, such as std.json, serde.zig, and comptime-bin, generate the field walk while the program compiles.

A @bitCast of a live suite value is not a valid encoding. Slices inside that value are pointers, not payload bytes. See Not a @bitCast.

Suite-specific gotchas

The capnproto row needs libcapnp and libkj under ~/.local.

Some serde.zig rows support only the message and strings data types.

These times cannot be ranked against another language.

Where to go next

The steps to install the toolchain and run the benchmark are in zig/README.md. The language overview is Zig overview.

Benchmark runner

  • Directory: zig/ (repository root)
  • Output: logs/zig/YYYY-MM-DD-HHMMSS.csv (Language=zig, times in nanoseconds)
  • Runner: zig/scripts/run-benchmarks.sh {smoke|all-single|full|research}
  • Registration: zig/src/serializers.zig

The shell script resolves the run config to JSON. The Zig binary does not spawn Python. Prepare is untimed. The harness owns a reusable output buffer per serializer. Timed I/O is serialize plus deserialize only. Schedule is SHA-256 + SplitMix64 Fisher–Yates (golden vector C, B, A).

Serializers (wired)

Name Category Package Stream Notes
std.json JSON std text_on_stream Stringify.value + parseFromSlice into the suite struct
std.json.scanner JSON std text_on_stream Same stringify; decode is Scanner + parseFromTokenSource
std.zon ZON std text_on_stream Official std.zon.stringify + std.zon.parse.fromSliceAlloc
comptime-bin Binary in-tree adapted Comptime field walk; LE ints; u32 length + bytes for strings
serde.json JSON serde.zig 1.0.7 adapted One comptime API, JSON path
serde.msgpack Binary serde.zig 1.0.7 adapted Same API, MessagePack
serde.yaml Text serde.zig 1.0.7 text_on_stream Same API, YAML. message / strings only
serde.toml Text serde.zig 1.0.7 text_on_stream Same API, TOML
serde.zon Text serde.zig 1.0.7 text_on_stream Same API, Zig Object Notation
serde.xml Text serde.zig 1.0.7 text_on_stream Same API, XML. message / strings only
zig-msgpack Binary zigcc/zig-msgpack 0.0.14 adapted Official MessagePack Payload API
msgpack.zig Binary lalinsky/msgpack.zig 0.7.0 native Typed encode / decodeFromSlice
zbor Binary r4gus/zbor 0.21.0 adapted Native Zig CBOR (stringify / parse)
s2s Binary ziglibs/s2s native Native binary “struct to stream”
protobuf Schema Arwalk/zig-protobuf 5.0.0 adapted Generated from schemas/v2/protobuf/benchmark_v2.proto. Prepare copies suite → generated message; timed path is encode / decode
flatbuffers Schema nDimensional/zig-flatbuffers 0.2.1 adapted Generated from cpp/schemas/benchmark.fbs. Timed path is Builder.writeTable / decodeRoot
capnproto Schema Cap’n Proto C++ 1.0.2 adapted Generated from cpp/schemas/benchmark.capnp. Official C++ runtime via a C ABI (same pattern as Swift). Zig 0.16 has no native plugin

Not a @bitCast of the whole fixture

A live suite value has []const u8 slices. @bitCast of that type is not a portable encoding. comptime-bin is the honest idiomatic stand-in: comptime reflection writes a length-prefixed little-endian image.

Schema generation

These rows compile the same suite IDLs as the other languages. They do not invent Zig-only schemas.

Row Shared schema Regenerate
protobuf schemas/v2/protobuf/benchmark_v2.proto ./zig/scripts/generate-protobuf.sh
flatbuffers cpp/schemas/benchmark.fbs ./zig/scripts/generate-flatbuffers.sh
capnproto cpp/schemas/benchmark.capnp ./zig/scripts/generate-capnp.sh

Prepare copies each suite fixture into the library’s native form (untimed). The timer measures encode and decode only. Fidelity copies back to the suite struct after decode.

capnproto uses the official C++ library (like Swift) because the Zig Cap’n Proto plugin requires Zig 0.17-dev. The host needs libcapnp / libkj under ~/.local (./scripts/install-host-requirements.sh zig).

Dashboard