C
C serialization is fragmented: each library owns its own object model (DOM trees, streams, generated structs).
Benchmark runner
c/(repository root)- Logs:
logs/c/YYYY-MM-DD-HHMMSS.csv - Build: CMake, C11 (+ C++17 for Google libprotobuf)
- Deps:
c/scripts/fetch-and-build-deps.sh; Google protobuf:cpp/scripts/setup-protobuf-sysroot.sh - Registration:
c/src/register_serializers.c - Domain shape: map-style codecs use a single visitor in
c/src/v2_codec.c(v2_write_fixture/v2_read_fixture). Wrappers implement library ops only—they do not hard-code V2 field graphs.
Serializers
| Name | Category | Timed path (what the row measures) |
|---|---|---|
| cJSON, yyjson, jansson, parson, json-c | JSON | Library DOM build + print / parse via visitor ops |
| custom-binary | Binary | Suite length-prefixed V2 baseline (bin_write_fixture / bin_read_fixture) |
| flatcc, avro-c | Schema | Real flatcc builder / avro-c iface write-read wrapping V2 payload bytes |
| libbson | Binary | bson_append_* / bson_iter_* via visitor ops |
| mpack, msgpack-c | Binary | Fixed-buffer map pack + tree/object unpack via visitor ops |
| nanopb, protobuf-c, protobuf-wire | Schema | Shared in-tree proto3 wire for V2 (fixture_pb_v2.h, same field tags as schemas/v2/protobuf/benchmark_v2.proto). Log names stay separate for historical comparison; not full nanopb stream codegen, protoc-gen-c descriptors, or Google upb. |
| protobuf | Schema | Google libprotobuf SerializeToArray / ParseFromArray on generated benchmark_v2.proto messages |
| tinycbor, cbor-encode (libcbor), qcbor, zcbor | Binary/schema | Native CBOR map encode via visitor ops; decode via tinycbor map walker (standard CBOR interop) where noted |
| ubj | Binary | In-tree UBJSON markers around suite V2 binary payload (bin_*) |
Pins: c/third_party/VERSIONS.md.
Caveats
- Visitor (map codecs): JSON / MessagePack / CBOR / BSON serializers only implement library primitives; field layout lives in
v2_codec.c. - Protobuf family honesty: the official Google row is
protobuf(libprotobuf + sysroot).nanopb/protobuf-c/protobuf-wirecurrently time the sharedfixture_pb_v2wire codec (domain encode/decode), not each library’s full generated-message stack. Do not read those three as “full library codegen benchmarks.” - Payload-wrapped:
ubj,flatcc, andavro-ckeep kind + binary payload (or builder vector) without full multi-type schema codegen. - Symbol prefixing:
parsonandtinycborare linked with renamed symbols so they co-exist withjanssonandlibcbor. - A serializer is registered only when its library is linked (CMake configure log
serializer: … REAL).
Stream honesty
Stream mode uses an in-memory FILE* (fmemopen) wrapper around full encode/decode buffers — StreamMode=adapted for every stream row. It is not a per-library incremental stream API. See Modes — stream honesty.