From dbde6ee447aadd40b6f87e0a8296edf716c346a0 Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Thu, 9 Jul 2026 19:05:46 +0200 Subject: [PATCH 01/13] Add canonical hash to Data --- CHANGELOG.md | 1 + src/compas/data/data.py | 61 ++++++++++++++++++++++++++++++++++ tests/compas/data/test_data.py | 29 ++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48f846510721..76f4845fdbf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `TOL.update()` method for explicit global state modification. * Added `TOL.temporary()` context manager for scoped changes. * Added missing implementation of `Brep.to_polygons()` in `compas_rhino.geometry.RhinoBrep`. +* Added `Data.canonical_hash()` for content-based hashing that is independent of guid, name, and serialization format (`sha256()` is unchanged). ### Changed diff --git a/src/compas/data/data.py b/src/compas/data/data.py index aaaf562f0bd1..d077d56707ec 100644 --- a/src/compas/data/data.py +++ b/src/compas/data/data.py @@ -10,6 +10,7 @@ pass import hashlib +import json from copy import deepcopy from uuid import UUID from uuid import uuid4 @@ -334,6 +335,66 @@ def sha256(self, as_string=False): return h.hexdigest() return h.digest() + def canonical_hash(self, as_string=False): + """Compute a content hash of the object that is independent of guid, name, and serialization format. + + Unlike :meth:`sha256`, which hashes the full JSON text of the object (including its + guid), this method hashes a canonical form of ``__dtype__`` + ``__data__`` only. Two + objects with the same type and data therefore produce the same hash regardless of their + guid/name, and regardless of which format (JSON, protobuf, ...) they were loaded from, + because every format reconstructs the same ``__data__``. + + Parameters + ---------- + as_string : bool, optional + If True, return the digest in hexadecimal format rather than as bytes. + + Returns + ------- + bytes | str + + See Also + -------- + :meth:`sha256` + + Notes + ----- + The canonical form is a UTF-8 JSON encoding of ``{"dtype", "data"}`` with sorted keys + and no insignificant whitespace, produced with the guid excluded from this object and + from any nested :class:`compas.data.Data` objects. This makes the hash suitable for + content-addressed change detection and version control, independent of the wire format. + + Examples + -------- + >>> from compas.geometry import Point + >>> a = Point(0, 0, 0) + >>> b = Point(0, 0, 0) + >>> a.guid == b.guid + False + >>> a.canonical_hash() == b.canonical_hash() + True + + """ + from compas.data import DataEncoder + + previous = DataEncoder.minimal + DataEncoder.minimal = True + try: + canonical = json.dumps( + self.__jsondump__(minimal=True), + cls=DataEncoder, + sort_keys=True, + separators=(",", ":"), + ) + finally: + DataEncoder.minimal = previous + + h = hashlib.sha256() + h.update(canonical.encode()) + if as_string: + return h.hexdigest() + return h.digest() + @classmethod def validate_data(cls, data): """Validate the data against the object's data schema. diff --git a/tests/compas/data/test_data.py b/tests/compas/data/test_data.py index e4f5bff67424..b66118334c1f 100644 --- a/tests/compas/data/test_data.py +++ b/tests/compas/data/test_data.py @@ -1,4 +1,6 @@ +import compas from compas.data import Data +from compas.geometry import Point def test_string_casting(): @@ -11,3 +13,30 @@ def __str__(self): test = TestClass(42) assert str(test) == "TestClass 42" + + +def test_canonical_hash_is_guid_independent(): + a = Point(1, 2, 3) + b = Point(1, 2, 3) + assert a.guid != b.guid + assert a.canonical_hash() == b.canonical_hash() + # sha256 is coupled to the guid, so it differs for these two + assert a.sha256() != b.sha256() + + +def test_canonical_hash_is_content_sensitive(): + assert Point(1, 2, 3).canonical_hash() != Point(1, 2, 4).canonical_hash() + + +def test_canonical_hash_is_stable_and_string_form(): + p = Point(1, 2, 3) + assert p.canonical_hash() == p.canonical_hash() + assert p.canonical_hash(as_string=True) == p.canonical_hash(as_string=True) + assert isinstance(p.canonical_hash(as_string=True), str) + assert isinstance(p.canonical_hash(), bytes) + + +def test_canonical_hash_survives_json_roundtrip(): + p = Point(1, 2, 3) + q = compas.json_loads(compas.json_dumps(p)) + assert q.canonical_hash() == p.canonical_hash() From 15cc0145359136a3bc9f2205ceb26223a02163f2 Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Thu, 9 Jul 2026 19:05:55 +0200 Subject: [PATCH 02/13] Add serialization PRD --- PRD-serialization.md | 304 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 PRD-serialization.md diff --git a/PRD-serialization.md b/PRD-serialization.md new file mode 100644 index 000000000000..270c54f1879a --- /dev/null +++ b/PRD-serialization.md @@ -0,0 +1,304 @@ +# PRD — Improving Serialization in COMPAS core + +**Status:** Draft / exploratory +**Author:** (you) +**Date:** 2026-07-07 +**Related code:** `compas.data` (JSON), `compas_pb` (protobuf), `arrow-opfs-poc` (zero-deserialization experiment) + +--- + +## 1. Summary + +COMPAS has two serialization modes today: + +1. **JSON (default, in core)** — human-readable, universal, self-describing via a + `dtype` string; implemented in `compas/data/`. +2. **Protobuf binary (opt-in, external)** — `compas_pb`, a plugin that maps + registered COMPAS types to hand-written `.proto` messages for a smaller, + faster wire format. + +Both are **row/object-oriented and fully deserializing**: every element is parsed +into a Python object on load. For COMPAS's heavy payloads — meshes, pointclouds, +graphs with millions of numeric values — this is the dominant cost in time, +memory, and (for JSON) size. This PRD scopes the problem and lays out candidate +directions, informed by a separate Arrow experiment showing that the expensive +part to eliminate is **deserialization**, not the unavoidable I/O copy. + +**This is a measurement-driven PRD.** No direction is adopted on argument alone; +each is decided against a benchmark suite built around two representative +large-data types — **`Mesh`** and **`Pointcloud`** — at varying sizes (§10). + +## 2. Background — current state + +### 2.1 JSON path (core) + +- `Data.__jsondump__()` produces `{"dtype", "data", "guid", "name"}`; + `__data__` is the per-class payload. +- `DataEncoder(json.JSONEncoder)` walks objects; `DataDecoder` reads `dtype` + (e.g. `"compas.geometry/Point"`), imports the class, and calls + `__from_data__(data)`. +- Entry points: `json_dump/dumps/load/loads`, plus zip-compressed + `json_dumpz/loadz`. Options: `pretty`, `compact`, `minimal`. +- Numpy arrays are flattened with `.tolist()`. +- **Coupling to hashing:** `Data.sha256()` hashes `json_dumps(self)`. Object + identity / change detection is therefore tied to the JSON text encoding. + +**Strengths:** universal, debuggable, no schema/codegen, forward/backward +tolerant. +**Weaknesses:** large (text + repeated keys), slow to parse, float precision +depends on `repr`, no columnar/bulk representation for numeric arrays. + +### 2.2 Protobuf path (`compas_pb`) + +- Plugin discovered via `compas_pb.plugins` entry-point group; a + `SerializerRegistry` maps `type → serializer` and `proto type_url → deserializer`, + registered by `@pb_serializer` / `@pb_deserializer` decorators in + `conversions.py`. +- Container schema (`message.proto`): `AnyData` is a `oneof` of a packed + `google.protobuf.Any`, a `struct.Value` primitive, or a `FallbackData` + wrapping a `DictData`. `MessageData` carries `data` + a `version` string. +- Hand-written `.proto` per type (`geometry.proto`, `datastructures.proto`) plus + two conversion functions per type. +- **Fallback:** unregistered `Data` subclasses are serialized as their + `__jsondump__()` dict inside a protobuf `DictData` — i.e. the JSON shape in a + protobuf envelope, with little size/speed benefit and still routed through the + JSON `DataDecoder` on the way back. + +**Strengths:** compact binary, schema'd, cross-language potential (any protobuf +runtime, including JS/Wasm), versioned envelope. +**Weaknesses (as-is):** + +- **Precision loss.** Geometry `.proto` stores coordinates as proto `float` + (32-bit IEEE-754). COMPAS geometry is float64 → **lossy round-trip** for + `x/y/z`, matrices, radii, angles. (To be quantified in the benchmark suite.) +- **Integer coercion.** The primitive path routes `int` through + `struct.Value.number_value` (float64), reconstructing `int` only when the + value `is_integer()`. Large/precise ints and the int/float distinction are at + risk. +- **Coverage & maintenance.** Every new type needs a `.proto` message, codegen, + and two hand-written functions. Anything not covered silently degrades to the + JSON-shaped fallback. +- **Brittle versioning.** `version` compatibility is an exact string match that + only emits a warning on mismatch. +- **Still fully deserializing.** Numeric bulk (vertices, faces) is decoded + element-by-element into Python objects, same as JSON. + +## 3. Motivation / problem statement + +1. **Heavy numeric payloads are the real cost.** A `Mesh`/`Pointcloud` with N + vertices pays O(N) Python-object construction on load in *both* modes. + Neither format has a bulk/columnar representation for coordinate and index + arrays. +2. **Browser & cross-language interop is growing** (web viewers, JS tooling). + JSON is large and slow there; protobuf needs generated JS stubs and still + deserializes fully. +3. **The binary path has correctness gaps** (float32, int coercion) that make it + unsafe as a silent drop-in for JSON today. +4. **Two divergent code paths** with different type coverage, guarantees, and + failure modes create a maintenance and correctness burden. + +## 4. Findings from the Arrow zero-deserialization experiment + +A sibling PoC (`arrow-opfs-poc`) moved large columnar data between Python and a +browser. The transferable conclusions: + +- **The boundary copy is unavoidable and cheap; deserialization is the expensive + part and *is* avoidable.** With a columnar layout (Arrow IPC), the receiver + points typed vectors straight at the received buffer — **zero per-element + parsing**. Proven both in Python (mmap; column buffer aliases the mapped file) + and in the browser (`Float64Array` aliases the fetched `ArrayBuffer`). +- **True cross-sandbox "same physical pages" zero-copy is impossible** (browser + has no mmap/shared memory with a foreign process). So the realistic target for + COMPAS is **zero-deserialization**, not zero-copy. +- **Implication for COMPAS:** representing the numeric-heavy parts of data + structures (vertex coordinates, face indices, pointclouds, transformation + matrices) as contiguous typed buffers would let both Python and JS consumers + skip per-element construction — the single biggest lever for large-model load + time and memory. `Mesh` and `Pointcloud` are the natural first targets. + +## 5. Goals / non-goals + +### Goals + +- Preserve JSON as the **default, universal** format; no regression for existing + files or callers. +- Make a binary mode that is a **lossless, safe** alternative to JSON (fix + float32/int issues) with a clear coverage-and-fallback contract. +- Introduce a path that avoids **per-element deserialization** for large numeric + arrays (columnar/buffer-backed), usable from both Python and the browser. +- Unify the two modes behind a **single, stable serialization API** with format + negotiation, so callers choose a format without divergent semantics. +- Keep object identity/versioning (`sha256`, schema) **format-independent**. +- **Decide every direction on measured evidence** from the §10 benchmark suite. + +### Non-goals + +- Replacing JSON as the default. +- True zero-copy across the browser boundary (physically impossible). +- Changing COMPAS object models / public class APIs. +- Solving streaming/partial loading in v1 (note it as future work). + +## 6. Constraints & assumptions + +- **IronPython/.NET is no longer a binding constraint.** The next major release + of COMPAS drops IronPython support. This removes the historical barrier to + numpy/pyarrow-based approaches and makes a columnar/typed-buffer path viable + much closer to the core rather than only in an isolated extension. +- **Backward compatibility.** Existing `.json` files must keep loading; `dtype` + resolution and `__from_data__` remain the contract. +- **Precision.** Geometry is float64; the default must be lossless and any binary + mode must be lossless unless the caller explicitly opts into a compact/lossy + profile. +- **Dependency weight, not availability, is the trade-off now.** pyarrow/numpy + are acceptable where they earn their keep; keep them optional extras so a + minimal core install stays light, but they are no longer disqualified by + runtime. + +## 7. Requirements + +### Functional + +- **F1** A single high-level API (e.g. `compas.data.dump/load`) that accepts a + `format=` selector (`"json" | "protobuf" | "arrow" | ...`) and produces/reads a + self-identifying container (magic bytes / MIME) so `load` can auto-detect. +- **F2** Round-trip **losslessness** for the default and the "safe binary" + profile across all registered COMPAS types (property-based equality tests). +- **F3** A documented **fallback contract**: unregistered types degrade + predictably (and loudly, not silently) with a single shared type-resolution + mechanism (`dtype` ↔ proto type_url ↔ Arrow schema metadata). +- **F4** A **columnar/buffer profile** for numeric-heavy structures (`Mesh` + vertices/faces, `Pointcloud`, transformation matrices) that reconstructs typed + arrays without per-element Python object creation. +- **F5** Format-independent **object hashing/versioning** (decouple `sha256` from + the JSON text; hash the canonical `__data__`/schema instead). + +### Non-functional + +- **N1** Binary/columnar load of a large `Mesh`/`Pointcloud` is materially faster + and lower-memory than JSON (targets set from the §10 baseline, not guessed). +- **N2** Default JSON path performance and behavior unchanged (no regression). +- **N3** Heavy deps (pyarrow/protobuf) isolated as optional extras; minimal core + install works without them. +- **N4** Clear, versioned wire format with a real compatibility policy (not an + exact-string warning). + +## 8. Candidate directions (to evaluate) + +These are not mutually exclusive; the likely answer is a layered combination. +**Each is gated on §10 benchmark results.** + +### Direction A — Harden & optionally accelerate the JSON path +- Decouple `sha256`/versioning from JSON text (canonical form). +- Optional fast encoder (e.g. `orjson`) behind the same API where available. +- *Pros:* low risk, immediate. *Cons:* doesn't address bulk-numeric cost. + +### Direction B — Make `compas_pb` a safe, first-class binary mode +- Fix precision: `double` not `float`; explicit int handling. +- Reduce per-type boilerplate (generate `.proto`/conversions from `__data__` + schema, or a reflective serializer) and define the fallback contract. +- Real version-compat policy. +- *Pros:* compact, cross-language, builds on existing work. *Cons:* still fully + deserializing; codegen/runtime dep for consumers. + +### Direction C — Columnar/buffer profile (Arrow-informed) for numeric bulk +- Encode `Mesh` vertex coords + face indices, `Pointcloud` points, and matrices + as contiguous typed buffers (Arrow IPC or a minimal home-grown buffer format); + keep metadata/attributes in a flexible container (JSON or protobuf). +- Reconstruct as numpy/typed arrays with **zero per-element parsing**; first-class + JS consumption via Arrow-JS in the browser. +- *Pros:* attacks the real bottleneck; strong browser story; now viable close to + core (no IronPython barrier). *Cons:* pyarrow dependency weight; hybrid layout + (bulk buffers + heterogeneous attributes) needs design. + +### Direction D — Unified serialization façade + format negotiation +- One API over all formats, self-identifying containers, shared type registry. +- Callers pick a format by capability/target (debugging → JSON; web/native bulk → + Arrow/protobuf) without semantic divergence. +- *Pros:* consolidates guarantees and coverage. *Cons:* design/coordination + effort; must not leak heavy deps into a minimal install. + +**Straw-man recommendation for discussion:** D as the umbrella; A first (cheap, +de-risks hashing); B to make binary *safe*; C for the numeric-heavy win — +**pending the numbers**, since C is only worth its dependency weight if the +measured `Mesh`/`Pointcloud` load-time and memory gains are large. + +## 9. Open questions + +- Where does the **type registry** live so JSON, protobuf, and Arrow share one + `dtype` ↔ schema mapping instead of three? +- Can `__data__` schemas be introspected to **auto-generate** binary encoders + (kill the per-type boilerplate), or is hand-tuning required for the hot types? +- What is the **canonical form** for hashing that is stable across formats? +- Attribute dictionaries are heterogeneous — do they stay in a flexible container + even in the columnar profile (hybrid layout)? (Likely yes.) +- Compatibility policy: semantic versioning of the wire format + capability flags + vs. current exact-string check. +- Is **streaming / partial load** (huge models) in scope later, and does the + chosen container support it? + +## 10. Benchmarking — the decision instrument + +Measurement is the backbone of this PRD, not an afterthought. Directions A–D are +accepted or rejected on these numbers. + +### 10.1 Corpus + +Two types stand in for "large data chunks", each at several sizes so we can see +scaling, not a single point: + +| Subject | Payload | Sizes (approx.) | +|--------------|-------------------------------------------|---------------------------------------| +| `Mesh` | vertices (float64 ×3) + faces (int index) | 10³, 10⁵, 10⁶, 5·10⁶ vertices | +| `Pointcloud` | points (float64 ×3), optional attributes | 10⁴, 10⁶, 10⁷, 5·10⁷ points | + +Include one variant **with per-element attributes** and one **without**, since +attribute dicts are the part a columnar layout cannot flatten — this exposes the +hybrid-layout cost. + +Fixtures should be generated deterministically (seeded) so runs are comparable, +and reused across all formats. + +### 10.2 Formats under test + +- JSON (`compact`), and JSON+zip (`json_dumpz`) as the size baseline. +- `compas_pb` as-is (float32) and a `double` variant (to isolate the precision + fix's size/speed cost). +- Columnar/Arrow prototype (Direction C). + +### 10.3 Metrics (per subject × size × format) + +- **Serialized size** (bytes on disk/wire); compression ratio vs JSON. +- **Serialize time** and **deserialize time** (wall clock, warm cache, multiple + runs → median + spread). +- **Peak memory** during deserialize (e.g. `tracemalloc` / RSS sampling). +- **Round-trip fidelity:** exact equality of `__data__`; for lossy profiles, + max/RMS coordinate error (this is where float32 gets quantified). +- **Browser** (Direction C): fetch→reconstruct time for the largest `Mesh`/ + `Pointcloud` in JS, and whether typed arrays alias the received buffer. + +### 10.4 Reporting + +A small, repeatable harness (script + fixtures) that emits a table/CSV per run, +committed alongside the PRD so results are reproducible and reviewable. Targets +for N1 are set **after** the baseline exists, expressed as a required factor +improvement over JSON for the largest sizes. + +## 11. Rough phasing + +1. **Baseline & harness.** Build the §10 corpus (`Mesh`, `Pointcloud`) and + benchmark harness; measure JSON and current `compas_pb`. Decouple `sha256` + from JSON text. *Exit:* a committed results table and agreed N1 targets. +2. **Safe binary.** Fix `compas_pb` precision/int issues; measure the `double` + cost; define fallback + version policy; expand/auto-generate coverage. +3. **Columnar prototype.** Arrow/buffer profile for `Mesh` + `Pointcloud`; Python + and browser reconstruction benchmarked against the baseline. *Go/no-go on the + measured gain vs pyarrow dependency weight.* +4. **Unified API.** Format negotiation + self-identifying containers + shared + registry; docs and migration guidance. + +--- + +*Appendix — key source references:* `compas/data/data.py`, +`compas/data/encoders.py`, `compas/data/json.py`; +`compas_pb/core.py`, `compas_pb/registry.py`, `compas_pb/conversions.py`, +`compas_pb/protobuf_defs/.../{message,geometry,datastructures}.proto`. From c68beb8a381336dff8f26e33cfeb98e083dedde0 Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Thu, 9 Jul 2026 19:06:20 +0200 Subject: [PATCH 03/13] Add benchmarks --- benchmarks/README.md | 105 ++++++++++ benchmarks/__init__.py | 0 benchmarks/serialization/__init__.py | 10 + benchmarks/serialization/fixtures.py | 91 +++++++++ benchmarks/serialization/formats.py | 112 +++++++++++ benchmarks/serialization/metrics.py | 114 +++++++++++ benchmarks/serialization/report.py | 277 +++++++++++++++++++++++++++ benchmarks/serialization/run.py | 184 ++++++++++++++++++ 8 files changed, 893 insertions(+) create mode 100644 benchmarks/README.md create mode 100644 benchmarks/__init__.py create mode 100644 benchmarks/serialization/__init__.py create mode 100644 benchmarks/serialization/fixtures.py create mode 100644 benchmarks/serialization/formats.py create mode 100644 benchmarks/serialization/metrics.py create mode 100644 benchmarks/serialization/report.py create mode 100644 benchmarks/serialization/run.py diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 000000000000..27d04d9f6e47 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,105 @@ +# Serialization benchmarks + +The measurement instrument for [`PRD-serialization.md`](../PRD-serialization.md). Directions A–D +in the PRD are accepted or rejected on the numbers this harness produces, not on argument. + +## What it measures (PRD §10) + +For each **subject × size × format**: + +- **serialized size** (bytes on the wire) and compression ratio vs JSON; +- **serialize** and **deserialize** time (median + spread over `--repeat` runs), the + **round-trip total**, and **throughput** (MB of wire per second) so formats are + comparable across sizes — this is how the impact of zipping / protobuf / Arrow gets read; +- **peak memory** during deserialize (`tracemalloc`); +- **round-trip fidelity**: exact equality of `__data__` and of the format-independent + `canonical_hash` — where a lossy profile (e.g. protobuf float32) will show up. + +## Subjects (PRD §10.1) + +| Subject | Payload | Attributes | +|---------------|--------------------------------------------|------------| +| `mesh` | jittered grid, float64 verts + int faces | none | +| `mesh_attrs` | same + a per-vertex float | per-element (hybrid-layout cost) | +| `pointcloud` | N float64 points | none¹ | + +¹ The COMPAS `Pointcloud` type has no per-point attribute slot, so the "with per-element +attributes" case lives on `mesh_attrs`. + +Fixtures are seeded ([`fixtures.py`](serialization/fixtures.py)) so runs are comparable and +reused across every format. + +## Formats under test + +Registered in [`formats.py`](serialization/formats.py): + +- `json` — compact text (the default, lossless); +- `json_zip` — zip-compressed JSON (size baseline); +- `compas_pb` — protobuf binary via the [`compas_pb`](https://pypi.org/project/compas_pb/) + plugin (optional dep; `pip install compas_pb`). Skipped automatically if not installed. + Currently **float32 → lossy** for float64 geometry; the harness quantifies the error + (see `max_abs_error` / `rms_error`). + +Later phases register a `compas_pb` `double` variant and an Arrow/columnar prototype the same +way; the runner picks up any registered, available format automatically and skips those whose +optional dependency is missing (`available=False`). + +## Running + +Every run writes a CSV **and** a self-contained, theme-aware HTML report next to it +(`results/.html`) — open it in a browser for a readable, per-subject view with +grouped bars (round-trip time, wire size) and a full table. The CSV is the machine +record; the HTML is the human one. + +```bash +# Quick baseline (small sizes, fast) — writes results/baseline_quick.{csv,html} +python -m benchmarks.serialization.run + +# Full PRD corpus (large; slow, memory-hungry) +python -m benchmarks.serialization.run --preset full --out benchmarks/serialization/results/baseline_full.csv + +# Subset +python -m benchmarks.serialization.run --subjects mesh pointcloud --formats json +``` + +Run from the repository root so `benchmarks` imports as a package. Requires a working +`numpy` (COMPAS geometry imports it at load time). + +## Results + +- `results/baseline_quick.{csv,html}` — JSON, JSON+zip, and `compas_pb` (**as shipped**, + float32) on the quick corpus. Findings: `json_zip` is 2–3.6× smaller than compact JSON + for ~1.5–1.8× slower round-trips; `compas_pb` as-is is **larger and slower than JSON** + and **lossy** (float32), with the error scaling with coordinate magnitude + (mesh ~1.5e-08, pointcloud ~3.8e-06). +- `results/pb_precision_compare.{csv,html}` — **Phase 2 precision probe**: `compas_pb` + float32 vs a `double` build. Double drives coordinate error to **0** and makes + `Pointcloud` fully lossless, for ~+6% (mesh) / ~+19% (pointcloud) wire size. `Mesh` + stays non-lossless even with double — but now purely from **int/float coercion** of + zero-valued `default_vertex_attributes` (magnitude error 0), a defect separate from + precision (PRD §2.2 "Integer coercion"). + +### Reproducing the `double` variant + +The `double` numbers come from an experimental branch of the external `compas_pb` repo, +not the shipped wheel: + +```bash +# in the compas_pb checkout, on a branch: +# flip float -> double in protobuf_defs/compas_pb/generated/geometry.proto (PointData etc.) +# regenerate with the pinned protoc (invocations.PROTOC_VERSION, 31.1): +protoc --proto_path=src/compas_pb/protobuf_defs \ + --python_out=src --pyi_out=src \ + src/compas_pb/protobuf_defs/compas_pb/generated/geometry.proto +pip install -e . # into the compas .venv +python -m benchmarks.serialization.run --formats json compas_pb --out benchmarks/serialization/results/pb_double.csv +pip install --force-reinstall --no-deps compas_pb # restore the as-shipped float32 build +``` + +## Status + +Phase 1: baseline harness + JSON numbers, plus `Data.canonical_hash()` decoupling object +identity from the JSON text (`sha256()` is unchanged). +Phase 2 (in progress): `compas_pb` measured; precision fix (double) quantified above. Still +open: the int-coercion fix, a real version-compat policy, and reducing per-type boilerplate. +N1 speed/memory targets for the columnar direction will be set from these baselines. diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/benchmarks/serialization/__init__.py b/benchmarks/serialization/__init__.py new file mode 100644 index 000000000000..dfb7d15ee589 --- /dev/null +++ b/benchmarks/serialization/__init__.py @@ -0,0 +1,10 @@ +"""Serialization benchmark harness for COMPAS core (PRD-serialization.md, phase 1). + +This package builds the measurement instrument the serialization PRD is decided +against: deterministic ``Mesh``/``Pointcloud`` fixtures at several sizes, a +pluggable registry of serialization formats, and metrics (size, serialize / +deserialize time, peak memory, round-trip fidelity). + +New formats (safe protobuf, Arrow/columnar) plug into ``formats.py`` without +touching the fixtures or the runner, so results stay comparable across phases. +""" diff --git a/benchmarks/serialization/fixtures.py b/benchmarks/serialization/fixtures.py new file mode 100644 index 000000000000..b4b08f624fe5 --- /dev/null +++ b/benchmarks/serialization/fixtures.py @@ -0,0 +1,91 @@ +"""Deterministic, seeded fixtures for the serialization benchmark. + +Two subjects stand in for "large numeric payloads" (PRD 10.1): + +* ``Mesh`` -- vertices (float64 x3) + integer face indices. Generated as a jittered + grid so the vertex/face counts and coordinates are reproducible. A ``with_attributes`` + variant attaches a per-vertex float, exposing the hybrid-layout cost that a columnar + format cannot flatten. +* ``Pointcloud`` -- N points (float64 x3). The COMPAS ``Pointcloud`` type has no + per-point attribute slot, so only a points-only variant exists here; the Mesh + attribute variant carries the "with per-element attributes" case. + +All generators are seeded so runs are comparable and fixtures are reused across +every format under test. +""" + +import math +import random + +from compas.datastructures import Mesh +from compas.geometry import Pointcloud + +DEFAULT_SEED = 42 + + +def make_mesh(n_vertices, with_attributes=False, seed=DEFAULT_SEED): + """Build a deterministic jittered-grid mesh with approximately ``n_vertices`` vertices. + + Parameters + ---------- + n_vertices : int + Target number of vertices. The mesh is a ``side x side`` grid with + ``side = round(sqrt(n_vertices))``, so the actual count is the nearest square. + with_attributes : bool, optional + If True, attach a seeded per-vertex float attribute (``quality``). + seed : int, optional + Seed for the coordinate jitter and attributes. + + Returns + ------- + :class:`compas.datastructures.Mesh` + """ + rng = random.Random(seed) + side = max(2, int(round(math.sqrt(n_vertices)))) + + vertices = [] + for y in range(side): + for x in range(side): + vertices.append([float(x), float(y), rng.uniform(-0.5, 0.5)]) + + faces = [] + for y in range(side - 1): + for x in range(side - 1): + i = y * side + x + faces.append([i, i + 1, i + 1 + side, i + side]) + + mesh = Mesh.from_vertices_and_faces(vertices, faces) + + if with_attributes: + for vertex in mesh.vertices(): + mesh.vertex_attribute(vertex, "quality", rng.uniform(0.0, 1.0)) + + return mesh + + +def make_pointcloud(n_points, seed=DEFAULT_SEED): + """Build a deterministic pointcloud of ``n_points`` float64 points. + + Parameters + ---------- + n_points : int + Number of points. + seed : int, optional + Seed for the point coordinates. + + Returns + ------- + :class:`compas.geometry.Pointcloud` + """ + rng = random.Random(seed) + points = [[rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0)] for _ in range(n_points)] + return Pointcloud(points) + + +# Subject catalogue: (label, factory taking a size -> Data object). +# Sizes follow PRD 10.1 but are selected by the runner (see run.py --sizes / --quick). +SUBJECTS = { + "mesh": lambda size, seed=DEFAULT_SEED: make_mesh(size, with_attributes=False, seed=seed), + "mesh_attrs": lambda size, seed=DEFAULT_SEED: make_mesh(size, with_attributes=True, seed=seed), + "pointcloud": lambda size, seed=DEFAULT_SEED: make_pointcloud(size, seed=seed), +} diff --git a/benchmarks/serialization/formats.py b/benchmarks/serialization/formats.py new file mode 100644 index 000000000000..c9648297a5fa --- /dev/null +++ b/benchmarks/serialization/formats.py @@ -0,0 +1,112 @@ +"""Registry of serialization formats under test. + +Each format is a :class:`Format` with ``dumps(obj) -> bytes`` and ``loads(bytes) -> obj``. +Phase 1 ships the two JSON baselines (compact text, and zip-compressed) that every +later format (safe protobuf, Arrow/columnar) is measured against. Register new +formats with :func:`register`; the runner picks them up automatically. + +Formats whose optional dependency (protobuf, pyarrow, ...) is missing should register +with ``available=False`` and be skipped by the runner rather than crashing it. +""" + +import io + +import compas + +_REGISTRY = {} + + +class Format(object): + """A named, round-trippable serialization format. + + Parameters + ---------- + name : str + Unique identifier used in result rows. + dumps : callable + ``obj -> bytes``. + loads : callable + ``bytes -> obj``. + available : bool, optional + False if a required optional dependency is missing; the runner skips it. + note : str, optional + Short human-readable description of the profile (e.g. "lossy float32"). + """ + + def __init__(self, name, dumps, loads, available=True, note=""): + self.name = name + self.dumps = dumps + self.loads = loads + self.available = available + self.note = note + + +def register(fmt): + _REGISTRY[fmt.name] = fmt + return fmt + + +def formats(): + """Return the registered formats in registration order.""" + return list(_REGISTRY.values()) + + +# --------------------------------------------------------------------------- +# JSON baselines (phase 1) +# --------------------------------------------------------------------------- + +def _json_compact_dumps(obj): + return compas.json_dumps(obj, compact=True).encode("utf-8") + + +def _json_compact_loads(blob): + return compas.json_loads(blob.decode("utf-8")) + + +def _json_zip_dumps(obj): + buffer = io.BytesIO() + compas.json_dumpz(obj, buffer, compact=True) + return buffer.getvalue() + + +def _json_zip_loads(blob): + return compas.json_loadz(io.BytesIO(blob)) + + +register(Format("json", _json_compact_dumps, _json_compact_loads, note="compact text, lossless")) +register(Format("json_zip", _json_zip_dumps, _json_zip_loads, note="zip-compressed json, size baseline")) + + +# --------------------------------------------------------------------------- +# Protobuf (compas_pb plugin, optional). float32 wire -> lossy for float64 geometry. +# --------------------------------------------------------------------------- + +try: + import compas_pb # noqa: F401 + + _PB_AVAILABLE = True +except ImportError: + _PB_AVAILABLE = False + + +def _pb_dumps(obj): + from compas_pb import pb_dump_bts + + return pb_dump_bts(obj) + + +def _pb_loads(blob): + from compas_pb import pb_load_bts + + return pb_load_bts(blob) + + +register( + Format( + "compas_pb", + _pb_dumps, + _pb_loads, + available=_PB_AVAILABLE, + note="protobuf binary, float32 (lossy)", + ) +) diff --git a/benchmarks/serialization/metrics.py b/benchmarks/serialization/metrics.py new file mode 100644 index 000000000000..894ec3795e73 --- /dev/null +++ b/benchmarks/serialization/metrics.py @@ -0,0 +1,114 @@ +"""Metrics for the serialization benchmark (PRD 10.3). + +For a given fixture object and format, :func:`measure` reports: + +* serialized size (bytes on the wire); +* serialize and deserialize time (median + spread over several runs); +* peak memory during deserialize (``tracemalloc``); +* round-trip fidelity: exact equality of ``__data__`` and of the format-independent + ``canonical_hash`` (this is where a lossy profile such as protobuf-float32 would show up). +""" + +import statistics +import time +import tracemalloc + + +def _time(callable_, repeat): + samples = [] + result = None + for _ in range(repeat): + start = time.perf_counter() + result = callable_() + samples.append(time.perf_counter() - start) + return result, samples + + +def _summarize(samples): + return { + "median_s": statistics.median(samples), + "min_s": min(samples), + "max_s": max(samples), + "stdev_s": statistics.pstdev(samples) if len(samples) > 1 else 0.0, + } + + +def _collect_numeric_pairs(a, b, out): + """Walk two same-shaped structures in parallel, collecting (original, roundtrip) numeric leaves. + + Returns False if the shapes diverge (e.g. a lossy format dropped keys or changed the + layout), in which case a coordinate error is not meaningful. + """ + if isinstance(a, bool) or isinstance(b, bool): + return a == b + if isinstance(a, dict) and isinstance(b, dict): + if set(a) != set(b): + return False + return all(_collect_numeric_pairs(a[k], b[k], out) for k in a) + if isinstance(a, (list, tuple)) and isinstance(b, (list, tuple)): + if len(a) != len(b): + return False + return all(_collect_numeric_pairs(x, y, out) for x, y in zip(a, b)) + if isinstance(a, (int, float)) and isinstance(b, (int, float)): + out.append((float(a), float(b))) + return True + return a == b + + +def numeric_error(original, roundtrip): + """Max-absolute and RMS error over paired numeric leaves of two ``__data__`` structures. + + This is where a lossy profile (e.g. protobuf float32) gets quantified (PRD 10.3). + Returns ``None`` errors when the structures are not comparable leaf-for-leaf. + """ + pairs = [] + if not _collect_numeric_pairs(original, roundtrip, pairs) or not pairs: + return {"max_abs_error": None, "rms_error": None} + diffs = [abs(x - y) for x, y in pairs] + rms = (sum(d * d for d in diffs) / len(diffs)) ** 0.5 + return {"max_abs_error": max(diffs), "rms_error": rms} + + +def measure(fmt, obj, repeat=5): + """Serialize/deserialize ``obj`` with ``fmt`` and return a metrics dict. + + Parameters + ---------- + fmt : :class:`.formats.Format` + obj : :class:`compas.data.Data` + repeat : int, optional + Number of timed runs; the median and spread are reported. + + Returns + ------- + dict + """ + blob, dump_samples = _time(lambda: fmt.dumps(obj), repeat) + roundtrip, load_samples = _time(lambda: fmt.loads(blob), repeat) + + # Peak memory during a single, untimed deserialize (tracemalloc perturbs timing). + tracemalloc.start() + tracemalloc.reset_peak() + fmt.loads(blob) + _, peak_bytes = tracemalloc.get_traced_memory() + tracemalloc.stop() + + data_equal = obj.__data__ == roundtrip.__data__ + hash_equal = obj.canonical_hash() == roundtrip.canonical_hash() + error = numeric_error(obj.__data__, roundtrip.__data__) + + row = { + "format": fmt.name, + "size_bytes": len(blob), + "peak_mem_bytes": peak_bytes, + "lossless": bool(data_equal and hash_equal), + "data_equal": bool(data_equal), + "canonical_hash_equal": bool(hash_equal), + "max_abs_error": error["max_abs_error"], + "rms_error": error["rms_error"], + } + for key, value in _summarize(dump_samples).items(): + row["dump_" + key] = value + for key, value in _summarize(load_samples).items(): + row["load_" + key] = value + return row diff --git a/benchmarks/serialization/report.py b/benchmarks/serialization/report.py new file mode 100644 index 000000000000..d3acc4be36b5 --- /dev/null +++ b/benchmarks/serialization/report.py @@ -0,0 +1,277 @@ +"""Render benchmark result rows as a self-contained, readable HTML report. + +The CSV is the machine record; this is the human view. One standalone ``.html`` file +(no external assets, theme-aware) with, per subject: grouped bars comparing formats at +each size on the metrics that matter (round-trip time and wire size), plus a full table. + +New formats (protobuf, Arrow, ...) need no changes here: colors are assigned to formats +in first-appearance order from a validated categorical palette, so the report grows with +the harness. +""" + +import datetime +import html + +# Validated categorical palette (dataviz skill reference instance): (light, dark) per slot. +_SERIES = [ + ("#2a78d6", "#3987e5"), # blue + ("#1baf7a", "#199e70"), # aqua + ("#eda100", "#c98500"), # yellow + ("#008300", "#008300"), # green + ("#4a3aa7", "#9085e9"), # violet + ("#e34948", "#e66767"), # red + ("#e87ba4", "#d55181"), # magenta + ("#eb6834", "#d95926"), # orange +] + +_METRICS = [ + ("roundtrip_median_s", "Round-trip time", "time"), + ("size_bytes", "Wire size", "bytes"), +] + + +def _fmt_int(n): + return "{:,}".format(int(n)) + + +def _fmt_bytes(n): + n = float(n) + for unit in ["B", "KB", "MB", "GB"]: + if n < 1024 or unit == "GB": + return "{:.1f} {}".format(n, unit) + n /= 1024.0 + + +def _fmt_time(seconds): + seconds = float(seconds) + if seconds < 1.0: + return "{:.1f} ms".format(seconds * 1000.0) + return "{:.3f} s".format(seconds) + + +def _fmt_value(value, kind): + return _fmt_bytes(value) if kind == "bytes" else _fmt_time(value) + + +def _fmt_error(value): + if value in (None, "", "None"): + return "—" + value = float(value) + if value == 0.0: + return "0" + return "{:.1e}".format(value) + + +def _color_map(rows): + order = [] + for r in rows: + if r["format"] not in order: + order.append(r["format"]) + return {name: _SERIES[i % len(_SERIES)] for i, name in enumerate(order)} + + +def _css(colors): + series_light = "\n".join(" --series-{}: {};".format(i + 1, lo) for i, (lo, _) in enumerate(_SERIES)) + series_dark = "\n".join(" --series-{}: {};".format(i + 1, hi) for i, (_, hi) in enumerate(_SERIES)) + return """ +:root { + --page: #f9f9f7; --surface: #fcfcfb; + --text-primary: #0b0b0b; --text-secondary: #52514e; --muted: #898781; + --grid: #e1e0d9; --track: #efeee9; --border: rgba(11,11,11,0.10); + --good: #006300; --critical: #d03b3b; +%SERIES_LIGHT% +} +@media (prefers-color-scheme: dark) { + :root { + --page: #0d0d0d; --surface: #1a1a19; + --text-primary: #ffffff; --text-secondary: #c3c2b7; --muted: #898781; + --grid: #2c2c2a; --track: #232322; --border: rgba(255,255,255,0.10); + --good: #0ca30c; --critical: #e66767; +%SERIES_DARK% + } +} +:root[data-theme="light"] { + --page:#f9f9f7; --surface:#fcfcfb; --text-primary:#0b0b0b; --text-secondary:#52514e; + --grid:#e1e0d9; --track:#efeee9; --border:rgba(11,11,11,0.10); +} +:root[data-theme="dark"] { + --page:#0d0d0d; --surface:#1a1a19; --text-primary:#ffffff; --text-secondary:#c3c2b7; + --grid:#2c2c2a; --track:#232322; --border:rgba(255,255,255,0.10); +} + +* { box-sizing: border-box; } +body { margin: 0; background: var(--page); color: var(--text-primary); + font-family: system-ui, -apple-system, "Segoe UI", sans-serif; line-height: 1.5; } +.wrap { max-width: 980px; margin: 0 auto; padding: 32px 20px 64px; } +h1 { font-size: 22px; margin: 0 0 4px; } +h2 { font-size: 17px; margin: 40px 0 12px; padding-top: 16px; border-top: 1px solid var(--grid); } +.meta { color: var(--text-secondary); font-size: 13px; margin: 0 0 8px; } +.legend { display: flex; flex-wrap: wrap; gap: 14px; margin: 16px 0 8px; } +.chip { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text-secondary); } +.dot { width: 11px; height: 11px; border-radius: 3px; flex: none; } +.metric-title { font-size: 13px; font-weight: 600; color: var(--text-secondary); margin: 18px 0 8px; } +.sizegroup { margin: 0 0 12px; } +.sizelabel { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; margin: 0 0 4px; } +.bar-row { display: grid; grid-template-columns: 96px 1fr auto; align-items: center; gap: 10px; padding: 3px 0; } +.bar-name { font-size: 12px; color: var(--text-secondary); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.track { background: var(--track); border-radius: 4px; height: 14px; overflow: hidden; } +.fill { height: 100%; border-radius: 4px; } +.bar-val { font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text-primary); white-space: nowrap; } +.tablewrap { overflow-x: auto; margin-top: 10px; border: 1px solid var(--border); border-radius: 8px; } +table { border-collapse: collapse; width: 100%; font-size: 13px; background: var(--surface); } +th, td { text-align: right; padding: 7px 12px; white-space: nowrap; font-variant-numeric: tabular-nums; } +th { color: var(--muted); font-weight: 600; border-bottom: 1px solid var(--grid); text-align: right; } +th:first-child, td:first-child, th:nth-child(2), td:nth-child(2) { text-align: left; } +tr + tr td { border-top: 1px solid var(--grid); } +.fmt-cell { display: inline-flex; align-items: center; gap: 7px; } +.badge { font-size: 12px; font-weight: 600; } +.badge.ok { color: var(--good); } +.badge.no { color: var(--critical); } +.note { color: var(--muted); font-size: 12px; } +""".replace("%SERIES_LIGHT%", series_light).replace("%SERIES_DARK%", series_dark) + + +def _slot(colors, fmt): + # 1-based series index matching --series-N + return list(colors).index(fmt) % len(_SERIES) + 1 + + +def _legend(rows, colors): + parts = ['
'] + seen = [] + for r in rows: + if r["format"] in seen: + continue + seen.append(r["format"]) + slot = _slot(colors, r["format"]) + parts.append( + '' + "{} · {}".format(slot, html.escape(r["format"]), html.escape(r.get("note", ""))) + ) + parts.append("
") + return "".join(parts) + + +def _bars(subject_rows, colors, metric_key, kind): + # group by size (preserve order of first appearance) + sizes = [] + for r in subject_rows: + if r["size"] not in sizes: + sizes.append(r["size"]) + + blocks = [] + for size in sizes: + group = [r for r in subject_rows if r["size"] == size] + group_max = max(float(r[metric_key]) for r in group) or 1.0 + rows_html = [] + for r in group: + width = float(r[metric_key]) / group_max * 100.0 + slot = _slot(colors, r["format"]) + rows_html.append( + '
' + '
{name}
' + '
' + '
{val}
' + "
".format( + name=html.escape(r["format"]), + w=width, + s=slot, + val=_fmt_value(r[metric_key], kind), + ) + ) + blocks.append( + '
{lbl} elements
{rows}
'.format( + lbl=_fmt_int(size), rows="".join(rows_html) + ) + ) + return "".join(blocks) + + +def _table(subject_rows, colors): + head = ( + "sizeformatwire sizevs JSON" + "dumploadround-tripload MB/speak mem" + "max errlossless" + ) + body = [] + for r in subject_rows: + slot = _slot(colors, r["format"]) + lossless = str(r["lossless"]).lower() in ("true", "1") + badge = '✓ yes' if lossless else '✗ no' + body.append( + "" + "{size}" + '{fmt}' + "{wire}{ratio}×" + "{dump}{load}{trip}" + "{mbps}{mem}{err}{badge}" + "".format( + size=_fmt_int(r["size"]), + slot=slot, + fmt=html.escape(r["format"]), + wire=_fmt_bytes(r["size_bytes"]), + ratio=r["compression_vs_json"], + dump=_fmt_time(r["dump_median_s"]), + load=_fmt_time(r["load_median_s"]), + trip=_fmt_time(r["roundtrip_median_s"]), + mbps=r["load_mb_s"], + mem=_fmt_bytes(r["peak_mem_bytes"]), + err=_fmt_error(r.get("max_abs_error")), + badge=badge, + ) + ) + return '
{}{}
'.format(head, "".join(body)) + + +def build_html(rows, meta=None): + """Return a full standalone HTML document for the given result rows. + + Parameters + ---------- + rows : list[dict] + Result rows as produced by :func:`benchmarks.serialization.run.run`. + meta : dict, optional + Run metadata (preset, repeat, seed, ...) shown in the header. + + Returns + ------- + str + """ + meta = meta or {} + colors = _color_map(rows) + + subjects = [] + for r in rows: + if r["subject"] not in subjects: + subjects.append(r["subject"]) + + meta_bits = ["generated {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M"))] + for key in ("preset", "repeat", "seed", "compas"): + if key in meta: + meta_bits.append("{} {}".format(key, meta[key])) + + sections = [_legend(rows, colors)] + for subject in subjects: + subject_rows = [r for r in rows if r["subject"] == subject] + sections.append("

{}

".format(html.escape(subject))) + for metric_key, title, kind in _METRICS: + sections.append('
{}
'.format(html.escape(title))) + sections.append(_bars(subject_rows, colors, metric_key, kind)) + sections.append(_table(subject_rows, colors)) + + return ( + "" + "" + "COMPAS serialization benchmark" + "
" + "

COMPAS serialization benchmark

" + "

{meta}

" + "{body}" + "
" + ).format(css=_css(colors), meta=html.escape(" · ".join(meta_bits)), body="".join(sections)) + + +def write_html(rows, out_path, meta=None): + with open(out_path, "w") as f: + f.write(build_html(rows, meta)) + return out_path diff --git a/benchmarks/serialization/run.py b/benchmarks/serialization/run.py new file mode 100644 index 000000000000..4d37a8c83ab6 --- /dev/null +++ b/benchmarks/serialization/run.py @@ -0,0 +1,184 @@ +"""Runner for the serialization benchmark (PRD section 10). + +Iterates subjects x sizes x formats, builds each fixture once, measures every format +against it, prints a readable table, and writes a CSV. Targets for the PRD's N1 +("binary/columnar materially faster than JSON") are set from the numbers this emits. + +Examples +-------- +Quick baseline (default, small sizes, fast):: + + python -m benchmarks.serialization.run + +Full PRD corpus (large; slow and memory-hungry):: + + python -m benchmarks.serialization.run --preset full + +Subset:: + + python -m benchmarks.serialization.run --subjects mesh pointcloud --formats json +""" + +import argparse +import csv +import os + +import compas +from benchmarks.serialization import fixtures +from benchmarks.serialization import formats +from benchmarks.serialization import metrics +from benchmarks.serialization import report + +HERE = os.path.dirname(__file__) +RESULTS_DIR = os.path.join(HERE, "results") + +# Per-subject sizes. Mesh sizes are vertex counts; pointcloud sizes are point counts. +PRESETS = { + "quick": { + "mesh": [1000, 10000], + "mesh_attrs": [1000, 10000], + "pointcloud": [10000, 100000], + }, + "full": { # PRD 10.1 + "mesh": [1000, 100000, 1000000, 5000000], + "mesh_attrs": [1000, 100000, 1000000, 5000000], + "pointcloud": [10000, 1000000, 10000000, 50000000], + }, +} + +CSV_COLUMNS = [ + "subject", + "size", + "format", + "size_bytes", + "compression_vs_json", + # timing (seconds; median over --repeat runs, with spread) + "dump_median_s", + "dump_stdev_s", + "load_median_s", + "load_stdev_s", + "roundtrip_median_s", + # throughput on the serialized payload (MB of wire per second) + "dump_mb_s", + "load_mb_s", + "peak_mem_bytes", + "lossless", + "data_equal", + "canonical_hash_equal", + # fidelity of lossy profiles (float32 etc.) — quantified coordinate error + "max_abs_error", + "rms_error", + "note", +] + + +def _mb_per_s(size_bytes, seconds): + if not seconds: + return float("nan") + return round((size_bytes / 1e6) / seconds, 3) + + +def _human_bytes(n): + for unit in ["B", "KB", "MB", "GB"]: + if n < 1024 or unit == "GB": + return "{:.1f}{}".format(n, unit) + n /= 1024.0 + + +def run(subjects, preset, format_names, repeat, seed): + active_formats = [f for f in formats.formats() if f.available and (not format_names or f.name in format_names)] + if not active_formats: + raise SystemExit("No matching available formats.") + + rows = [] + sizes_by_subject = PRESETS[preset] + + for subject in subjects: + factory = fixtures.SUBJECTS[subject] + for size in sizes_by_subject[subject]: + obj = factory(size, seed) + measured = {f.name: metrics.measure(f, obj, repeat=repeat) for f in active_formats} + json_size = measured.get("json", {}).get("size_bytes") + + for fmt in active_formats: + m = measured[fmt.name] + ratio = (json_size / m["size_bytes"]) if json_size else float("nan") + roundtrip = m["dump_median_s"] + m["load_median_s"] + rows.append( + { + "subject": subject, + "size": size, + "format": fmt.name, + "size_bytes": m["size_bytes"], + "compression_vs_json": round(ratio, 3), + "dump_median_s": round(m["dump_median_s"], 6), + "dump_stdev_s": round(m["dump_stdev_s"], 6), + "load_median_s": round(m["load_median_s"], 6), + "load_stdev_s": round(m["load_stdev_s"], 6), + "roundtrip_median_s": round(roundtrip, 6), + "dump_mb_s": _mb_per_s(m["size_bytes"], m["dump_median_s"]), + "load_mb_s": _mb_per_s(m["size_bytes"], m["load_median_s"]), + "peak_mem_bytes": m["peak_mem_bytes"], + "lossless": m["lossless"], + "data_equal": m["data_equal"], + "canonical_hash_equal": m["canonical_hash_equal"], + "max_abs_error": m["max_abs_error"], + "rms_error": m["rms_error"], + "note": fmt.note, + } + ) + return rows + + +def print_table(rows): + header = "{:<12} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>8}".format( + "subject", "size", "format", "size", "dump_s", "load_s", "trip_s", "peak", "lossless" + ) + print(header) + print("-" * len(header)) + for r in rows: + print( + "{:<12} {:>10} {:>10} {:>10} {:>10.5f} {:>10.5f} {:>10.5f} {:>10} {:>8}".format( + r["subject"], + r["size"], + r["format"], + _human_bytes(r["size_bytes"]), + r["dump_median_s"], + r["load_median_s"], + r["roundtrip_median_s"], + _human_bytes(r["peak_mem_bytes"]), + str(r["lossless"]), + ) + ) + + +def write_csv(rows, out_path): + os.makedirs(os.path.dirname(out_path), exist_ok=True) + with open(out_path, "w", newline="") as f: + writer = csv.DictWriter(f, fieldnames=CSV_COLUMNS) + writer.writeheader() + for r in rows: + writer.writerow(r) + return out_path + + +def main(): + parser = argparse.ArgumentParser(description="COMPAS serialization benchmark (PRD phase 1).") + parser.add_argument("--subjects", nargs="+", choices=sorted(fixtures.SUBJECTS), default=sorted(fixtures.SUBJECTS)) + parser.add_argument("--preset", choices=sorted(PRESETS), default="quick") + parser.add_argument("--formats", nargs="*", default=None, help="Subset of format names; default all available.") + parser.add_argument("--repeat", type=int, default=5, help="Timed runs per measurement (median reported).") + parser.add_argument("--seed", type=int, default=fixtures.DEFAULT_SEED) + parser.add_argument("--out", default=os.path.join(RESULTS_DIR, "baseline_quick.csv"), help="CSV output path.") + args = parser.parse_args() + + rows = run(args.subjects, args.preset, args.formats, args.repeat, args.seed) + print_table(rows) + out = write_csv(rows, args.out) + meta = {"preset": args.preset, "repeat": args.repeat, "seed": args.seed, "compas": compas.__version__} + html_out = report.write_html(rows, os.path.splitext(out)[0] + ".html", meta=meta) + print("\nWrote {} rows to {}\nWrote report to {}".format(len(rows), out, html_out)) + + +if __name__ == "__main__": + main() From b26fd518bf39a3169a44e0fe7626c55375d0c6c6 Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Thu, 9 Jul 2026 19:06:37 +0200 Subject: [PATCH 04/13] Add results of first runs of benchmarks --- .../serialization/results/baseline_quick.csv | 19 +++++ .../serialization/results/baseline_quick.html | 70 +++++++++++++++++++ .../results/baseline_quick_double.csv | 19 +++++ .../results/baseline_quick_double.html | 70 +++++++++++++++++++ .../serialization/results/pb_double.csv | 13 ++++ .../serialization/results/pb_double.html | 70 +++++++++++++++++++ .../results/pb_precision_compare.csv | 19 +++++ .../results/pb_precision_compare.html | 70 +++++++++++++++++++ 8 files changed, 350 insertions(+) create mode 100644 benchmarks/serialization/results/baseline_quick.csv create mode 100644 benchmarks/serialization/results/baseline_quick.html create mode 100644 benchmarks/serialization/results/baseline_quick_double.csv create mode 100644 benchmarks/serialization/results/baseline_quick_double.html create mode 100644 benchmarks/serialization/results/pb_double.csv create mode 100644 benchmarks/serialization/results/pb_double.html create mode 100644 benchmarks/serialization/results/pb_precision_compare.csv create mode 100644 benchmarks/serialization/results/pb_precision_compare.html diff --git a/benchmarks/serialization/results/baseline_quick.csv b/benchmarks/serialization/results/baseline_quick.csv new file mode 100644 index 000000000000..46eab0f83db4 --- /dev/null +++ b/benchmarks/serialization/results/baseline_quick.csv @@ -0,0 +1,19 @@ +subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note +mesh,1000,json,82154,1.0,0.001583,7.3e-05,0.003765,0.000142,0.005348,51.891,21.821,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,json_zip,28052,2.929,0.003662,0.000222,0.003998,0.002349,0.00766,7.66,7.017,1615288,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,1000,compas_pb,185410,0.443,0.011866,0.008271,0.010729,0.00013,0.022596,15.625,17.281,1087150,False,False,False,1.4882048593456432e-08,2.5012009156355184e-09,"protobuf binary, float32 (lossy)" +mesh,10000,json,884888,1.0,0.019261,0.003012,0.052553,0.004602,0.071813,45.943,16.838,16027677,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,json_zip,243863,3.629,0.041683,0.002839,0.051803,0.005303,0.093486,5.85,4.708,16031054,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,10000,compas_pb,1862921,0.475,0.120204,0.002367,0.116941,0.004491,0.237145,15.498,15.93,10663623,False,False,False,1.4897168276739592e-08,2.4472232123975927e-09,"protobuf binary, float32 (lossy)" +mesh_attrs,1000,json,112098,1.0,0.001904,8.3e-05,0.00397,6.7e-05,0.005874,58.861,28.24,1666431,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,json_zip,38107,2.942,0.004875,6.7e-05,0.004451,0.000131,0.009326,7.817,8.562,1669264,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,1000,compas_pb,212034,0.529,0.015673,0.000478,0.013273,0.00063,0.028946,13.529,15.975,1279505,False,False,False,1.4882048593456432e-08,2.3344579357147124e-09,"protobuf binary, float32 (lossy)" +mesh_attrs,10000,json,1177508,1.0,0.022233,0.002673,0.050886,0.003608,0.073119,52.962,23.14,16560353,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,json_zip,347077,3.393,0.052582,0.003093,0.054935,0.005467,0.107517,6.601,6.318,16563482,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,10000,compas_pb,2122924,0.555,0.150893,0.00196,0.140561,0.006571,0.291453,14.069,15.103,12576001,False,False,False,1.4897168276739592e-08,2.2875342499681117e-09,"protobuf binary, float32 (lossy)" +pointcloud,10000,json,580633,1.0,0.014534,0.00012,0.014743,0.003123,0.029277,39.95,39.384,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,json_zip,280728,2.068,0.0367,0.004352,0.015156,0.003125,0.051855,7.649,18.523,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,10000,compas_pb,620120,0.936,0.018244,0.015125,0.028057,0.004947,0.046301,33.991,22.102,6113793,False,False,False,3.814631440945959e-06,1.4766756134925858e-06,"protobuf binary, float32 (lossy)" +pointcloud,100000,json,5804860,1.0,0.161026,0.004842,0.234024,0.021323,0.39505,36.049,24.805,42597425,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,json_zip,2792759,2.079,0.374419,0.007617,0.218703,0.018553,0.593123,7.459,12.77,42604858,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,100000,compas_pb,6200123,0.936,0.168653,0.13468,0.333715,0.014011,0.502368,36.763,18.579,61095745,False,False,False,3.8146725387377955e-06,1.4802791418516803e-06,"protobuf binary, float32 (lossy)" diff --git a/benchmarks/serialization/results/baseline_quick.html b/benchmarks/serialization/results/baseline_quick.html new file mode 100644 index 000000000000..6d50c3405141 --- /dev/null +++ b/benchmarks/serialization/results/baseline_quick.html @@ -0,0 +1,70 @@ +COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:34 · preset quick · repeat 5 · seed 42 · compas 2.15.0-e03e4097

json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, float32 (lossy)

mesh

Round-trip time
1,000 elements
json
5.3 ms
json_zip
7.7 ms
compas_pb
22.6 ms
10,000 elements
json
71.8 ms
json_zip
93.5 ms
compas_pb
237.1 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
181.1 KB
10,000 elements
json
864.1 KB
json_zip
238.1 KB
compas_pb
1.8 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.8 ms5.3 ms21.8211.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.7 ms4.0 ms7.7 ms7.0171.5 MB0✓ yes
1,000compas_pb181.1 KB0.443×11.9 ms10.7 ms22.6 ms17.2811.0 MB1.5e-08✗ no
10,000json864.1 KB1.0×19.3 ms52.6 ms71.8 ms16.83815.3 MB0✓ yes
10,000json_zip238.1 KB3.629×41.7 ms51.8 ms93.5 ms4.70815.3 MB0✓ yes
10,000compas_pb1.8 MB0.475×120.2 ms116.9 ms237.1 ms15.9310.2 MB1.5e-08✗ no

mesh_attrs

Round-trip time
1,000 elements
json
5.9 ms
json_zip
9.3 ms
compas_pb
28.9 ms
10,000 elements
json
73.1 ms
json_zip
107.5 ms
compas_pb
291.5 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
207.1 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
2.0 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms4.0 ms5.9 ms28.241.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.9 ms4.5 ms9.3 ms8.5621.6 MB0✓ yes
1,000compas_pb207.1 KB0.529×15.7 ms13.3 ms28.9 ms15.9751.2 MB1.5e-08✗ no
10,000json1.1 MB1.0×22.2 ms50.9 ms73.1 ms23.1415.8 MB0✓ yes
10,000json_zip338.9 KB3.393×52.6 ms54.9 ms107.5 ms6.31815.8 MB0✓ yes
10,000compas_pb2.0 MB0.555×150.9 ms140.6 ms291.5 ms15.10312.0 MB1.5e-08✗ no

pointcloud

Round-trip time
10,000 elements
json
29.3 ms
json_zip
51.9 ms
compas_pb
46.3 ms
100,000 elements
json
395.1 ms
json_zip
593.1 ms
compas_pb
502.4 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
605.6 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
5.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×14.5 ms14.7 ms29.3 ms39.3844.1 MB0✓ yes
10,000json_zip274.1 KB2.068×36.7 ms15.2 ms51.9 ms18.5234.1 MB0✓ yes
10,000compas_pb605.6 KB0.936×18.2 ms28.1 ms46.3 ms22.1025.8 MB3.8e-06✗ no
100,000json5.5 MB1.0×161.0 ms234.0 ms395.1 ms24.80540.6 MB0✓ yes
100,000json_zip2.7 MB2.079×374.4 ms218.7 ms593.1 ms12.7740.6 MB0✓ yes
100,000compas_pb5.9 MB0.936×168.7 ms333.7 ms502.4 ms18.57958.3 MB3.8e-06✗ no
\ No newline at end of file diff --git a/benchmarks/serialization/results/baseline_quick_double.csv b/benchmarks/serialization/results/baseline_quick_double.csv new file mode 100644 index 000000000000..228447e036a8 --- /dev/null +++ b/benchmarks/serialization/results/baseline_quick_double.csv @@ -0,0 +1,19 @@ +subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note +mesh,1000,json,82154,1.0,0.001567,9e-05,0.003719,8.2e-05,0.005287,52.418,22.088,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,json_zip,28049,2.929,0.003484,0.000134,0.004413,0.003348,0.007897,8.05,6.356,1615288,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,1000,compas_pb,197442,0.416,0.012311,0.008889,0.010525,0.000287,0.022835,16.038,18.76,1086758,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +mesh,10000,json,884888,1.0,0.0184,0.00301,0.048039,0.003817,0.066439,48.093,18.42,16027677,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,json_zip,243868,3.629,0.04081,0.002845,0.048154,0.003762,0.088964,5.976,5.064,16031062,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,10000,compas_pb,1982121,0.446,0.117473,0.003334,0.116975,0.005821,0.234448,16.873,16.945,10663259,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +mesh_attrs,1000,json,112098,1.0,0.001941,0.000164,0.004592,0.00053,0.006532,57.759,24.413,1666431,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,json_zip,38109,2.942,0.00545,0.00053,0.004582,0.000389,0.010031,6.993,8.318,1669256,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,1000,compas_pb,224066,0.5,0.015172,0.000624,0.013195,0.000381,0.028367,14.768,16.982,1279505,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +mesh_attrs,10000,json,1177508,1.0,0.022469,0.002624,0.051467,0.004636,0.073937,52.405,22.879,16560353,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,json_zip,347079,3.393,0.05392,0.004,0.053599,0.005939,0.107519,6.437,6.475,16563482,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,10000,compas_pb,2242124,0.525,0.144902,0.001894,0.136261,0.004908,0.281164,15.473,16.455,12576001,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +pointcloud,10000,json,580633,1.0,0.014378,0.000746,0.014751,0.002958,0.029129,40.384,39.363,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,json_zip,280725,2.068,0.03434,0.002842,0.014972,0.00311,0.049311,8.175,18.75,4264079,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,10000,compas_pb,740120,0.785,0.016721,0.014406,0.02714,0.004643,0.043861,44.264,27.27,6113793,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" +pointcloud,100000,json,5804860,1.0,0.155892,0.001105,0.208787,0.017486,0.364679,37.236,27.803,42597425,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,json_zip,2792754,2.079,0.36917,0.004919,0.217333,0.019755,0.586503,7.565,12.85,42604858,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,100000,compas_pb,7400123,0.784,0.163784,0.131419,0.320664,0.014701,0.484448,45.182,23.078,61095745,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" diff --git a/benchmarks/serialization/results/baseline_quick_double.html b/benchmarks/serialization/results/baseline_quick_double.html new file mode 100644 index 000000000000..57138c1c901c --- /dev/null +++ b/benchmarks/serialization/results/baseline_quick_double.html @@ -0,0 +1,70 @@ +COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:42 · preset quick · repeat 5 · seed 42 · compas 2.15.0-e03e4097

json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, float32 (lossy)

mesh

Round-trip time
1,000 elements
json
5.3 ms
json_zip
7.9 ms
compas_pb
22.8 ms
10,000 elements
json
66.4 ms
json_zip
89.0 ms
compas_pb
234.4 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
192.8 KB
10,000 elements
json
864.1 KB
json_zip
238.2 KB
compas_pb
1.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.7 ms5.3 ms22.0881.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.5 ms4.4 ms7.9 ms6.3561.5 MB0✓ yes
1,000compas_pb192.8 KB0.416×12.3 ms10.5 ms22.8 ms18.761.0 MB0✗ no
10,000json864.1 KB1.0×18.4 ms48.0 ms66.4 ms18.4215.3 MB0✓ yes
10,000json_zip238.2 KB3.629×40.8 ms48.2 ms89.0 ms5.06415.3 MB0✓ yes
10,000compas_pb1.9 MB0.446×117.5 ms117.0 ms234.4 ms16.94510.2 MB0✗ no

mesh_attrs

Round-trip time
1,000 elements
json
6.5 ms
json_zip
10.0 ms
compas_pb
28.4 ms
10,000 elements
json
73.9 ms
json_zip
107.5 ms
compas_pb
281.2 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
218.8 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
2.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms4.6 ms6.5 ms24.4131.6 MB0✓ yes
1,000json_zip37.2 KB2.942×5.5 ms4.6 ms10.0 ms8.3181.6 MB0✓ yes
1,000compas_pb218.8 KB0.5×15.2 ms13.2 ms28.4 ms16.9821.2 MB0✗ no
10,000json1.1 MB1.0×22.5 ms51.5 ms73.9 ms22.87915.8 MB0✓ yes
10,000json_zip338.9 KB3.393×53.9 ms53.6 ms107.5 ms6.47515.8 MB0✓ yes
10,000compas_pb2.1 MB0.525×144.9 ms136.3 ms281.2 ms16.45512.0 MB0✗ no

pointcloud

Round-trip time
10,000 elements
json
29.1 ms
json_zip
49.3 ms
compas_pb
43.9 ms
100,000 elements
json
364.7 ms
json_zip
586.5 ms
compas_pb
484.4 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
722.8 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
7.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×14.4 ms14.8 ms29.1 ms39.3634.1 MB0✓ yes
10,000json_zip274.1 KB2.068×34.3 ms15.0 ms49.3 ms18.754.1 MB0✓ yes
10,000compas_pb722.8 KB0.785×16.7 ms27.1 ms43.9 ms27.275.8 MB0✓ yes
100,000json5.5 MB1.0×155.9 ms208.8 ms364.7 ms27.80340.6 MB0✓ yes
100,000json_zip2.7 MB2.079×369.2 ms217.3 ms586.5 ms12.8540.6 MB0✓ yes
100,000compas_pb7.1 MB0.784×163.8 ms320.7 ms484.4 ms23.07858.3 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/results/pb_double.csv b/benchmarks/serialization/results/pb_double.csv new file mode 100644 index 000000000000..8104f510b635 --- /dev/null +++ b/benchmarks/serialization/results/pb_double.csv @@ -0,0 +1,13 @@ +subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note +mesh,1000,json,82154,1.0,0.001589,9.4e-05,0.003713,0.000104,0.005302,51.694,22.128,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,compas_pb,197442,0.416,0.011683,0.007519,0.010649,0.002442,0.022332,16.9,18.541,1087122,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +mesh,10000,json,884888,1.0,0.018243,0.003325,0.048497,0.005433,0.06674,48.506,18.246,16028133,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,compas_pb,1982121,0.446,0.118464,0.001636,0.119897,0.007634,0.238361,16.732,16.532,10663371,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +mesh_attrs,1000,json,112098,1.0,0.001899,5.2e-05,0.003945,0.00026,0.005844,59.043,28.413,1666239,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,compas_pb,224066,0.5,0.015348,0.000632,0.013972,0.006161,0.02932,14.599,16.037,1279505,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +mesh_attrs,10000,json,1177508,1.0,0.021897,0.002534,0.050358,0.004144,0.072255,53.774,23.383,16560465,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,compas_pb,2242124,0.525,0.145139,0.002585,0.135914,0.006323,0.281053,15.448,16.497,12576001,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" +pointcloud,10000,json,580633,1.0,0.014235,0.00017,0.014198,0.003257,0.028433,40.789,40.897,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,compas_pb,740120,0.785,0.016236,0.012043,0.026997,0.004063,0.043233,45.586,27.415,6114057,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" +pointcloud,100000,json,5804860,1.0,0.155184,0.001999,0.200165,0.008131,0.355349,37.406,29.0,42597425,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,compas_pb,7400123,0.784,0.163579,0.135658,0.332765,0.016538,0.496344,45.239,22.238,61095745,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" diff --git a/benchmarks/serialization/results/pb_double.html b/benchmarks/serialization/results/pb_double.html new file mode 100644 index 000000000000..978bd6cb7a7c --- /dev/null +++ b/benchmarks/serialization/results/pb_double.html @@ -0,0 +1,70 @@ +COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:28 · preset quick · repeat 5 · seed 42 · compas 2.15.0-e03e4097

json · compact text, losslesscompas_pb · protobuf binary, float32 (lossy)

mesh

Round-trip time
1,000 elements
json
5.3 ms
compas_pb
22.3 ms
10,000 elements
json
66.7 ms
compas_pb
238.4 ms
Wire size
1,000 elements
json
80.2 KB
compas_pb
192.8 KB
10,000 elements
json
864.1 KB
compas_pb
1.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.7 ms5.3 ms22.1281.5 MB0✓ yes
1,000compas_pb192.8 KB0.416×11.7 ms10.6 ms22.3 ms18.5411.0 MB0✗ no
10,000json864.1 KB1.0×18.2 ms48.5 ms66.7 ms18.24615.3 MB0✓ yes
10,000compas_pb1.9 MB0.446×118.5 ms119.9 ms238.4 ms16.53210.2 MB0✗ no

mesh_attrs

Round-trip time
1,000 elements
json
5.8 ms
compas_pb
29.3 ms
10,000 elements
json
72.3 ms
compas_pb
281.1 ms
Wire size
1,000 elements
json
109.5 KB
compas_pb
218.8 KB
10,000 elements
json
1.1 MB
compas_pb
2.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms3.9 ms5.8 ms28.4131.6 MB0✓ yes
1,000compas_pb218.8 KB0.5×15.3 ms14.0 ms29.3 ms16.0371.2 MB0✗ no
10,000json1.1 MB1.0×21.9 ms50.4 ms72.3 ms23.38315.8 MB0✓ yes
10,000compas_pb2.1 MB0.525×145.1 ms135.9 ms281.1 ms16.49712.0 MB0✗ no

pointcloud

Round-trip time
10,000 elements
json
28.4 ms
compas_pb
43.2 ms
100,000 elements
json
355.3 ms
compas_pb
496.3 ms
Wire size
10,000 elements
json
567.0 KB
compas_pb
722.8 KB
100,000 elements
json
5.5 MB
compas_pb
7.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×14.2 ms14.2 ms28.4 ms40.8974.1 MB0✓ yes
10,000compas_pb722.8 KB0.785×16.2 ms27.0 ms43.2 ms27.4155.8 MB0✓ yes
100,000json5.5 MB1.0×155.2 ms200.2 ms355.3 ms29.040.6 MB0✓ yes
100,000compas_pb7.1 MB0.784×163.6 ms332.8 ms496.3 ms22.23858.3 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/results/pb_precision_compare.csv b/benchmarks/serialization/results/pb_precision_compare.csv new file mode 100644 index 000000000000..0ec2ed325f45 --- /dev/null +++ b/benchmarks/serialization/results/pb_precision_compare.csv @@ -0,0 +1,19 @@ +subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note +mesh,1000,json,82154,1.0,0.001516,0.000129,0.00374,0.000119,0.005256,54.181,21.968,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,compas_pb_f32,185410,0.443,0.011516,0.010525,0.010121,0.000869,0.021637,16.1,18.32,1086926,False,False,False,1.4882048593456432e-08,2.5012009156355184e-09,"protobuf, float32 (as shipped)" +mesh,1000,compas_pb_f64,197442,0.416,0.011683,0.007519,0.010649,0.002442,0.022332,16.9,18.541,1087122,False,True,False,0.0,0.0,"protobuf, double (branch)" +mesh,10000,json,884888,1.0,0.016997,0.003222,0.045805,0.003729,0.062802,52.062,19.319,16027677,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,compas_pb_f32,1862921,0.475,0.114164,0.001157,0.113307,0.003653,0.227471,16.318,16.441,10663651,False,False,False,1.4897168276739592e-08,2.4472232123975927e-09,"protobuf, float32 (as shipped)" +mesh,10000,compas_pb_f64,1982121,0.446,0.118464,0.001636,0.119897,0.007634,0.238361,16.732,16.532,10663371,False,True,False,0.0,0.0,"protobuf, double (branch)" +mesh_attrs,1000,json,112098,1.0,0.001879,3.7e-05,0.003821,3.7e-05,0.0057,59.668,29.336,1666431,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,compas_pb_f32,212034,0.529,0.013908,6.4e-05,0.012577,0.000185,0.026486,15.245,16.858,1279505,False,False,False,1.4882048593456432e-08,2.3344579357147124e-09,"protobuf, float32 (as shipped)" +mesh_attrs,1000,compas_pb_f64,224066,0.5,0.015348,0.000632,0.013972,0.006161,0.02932,14.599,16.037,1279505,False,True,False,0.0,0.0,"protobuf, double (branch)" +mesh_attrs,10000,json,1177508,1.0,0.020361,0.002154,0.047704,0.005262,0.068064,57.833,24.684,16560353,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,compas_pb_f32,2122924,0.555,0.143979,0.001996,0.133149,0.004651,0.277128,14.745,15.944,12576001,False,False,False,1.4897168276739592e-08,2.2875342499681117e-09,"protobuf, float32 (as shipped)" +mesh_attrs,10000,compas_pb_f64,2242124,0.525,0.145139,0.002585,0.135914,0.006323,0.281053,15.448,16.497,12576001,False,True,False,0.0,0.0,"protobuf, double (branch)" +pointcloud,10000,json,580633,1.0,0.013667,0.000176,0.013718,0.002513,0.027384,42.485,42.327,4261476,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,compas_pb_f32,620120,0.936,0.016915,0.013203,0.02747,0.003954,0.044385,36.662,22.574,6113793,False,False,False,3.814631440945959e-06,1.4766756134925858e-06,"protobuf, float32 (as shipped)" +pointcloud,10000,compas_pb_f64,740120,0.785,0.016236,0.012043,0.026997,0.004063,0.043233,45.586,27.415,6114057,True,True,True,0.0,0.0,"protobuf, double (branch)" +pointcloud,100000,json,5804860,1.0,0.14816,0.001288,0.194884,0.015763,0.343044,39.18,29.786,42597367,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,compas_pb_f32,6200123,0.936,0.171329,0.1231,0.321633,0.015959,0.492962,36.188,19.277,61095745,False,False,False,3.8146725387377955e-06,1.4802791418516803e-06,"protobuf, float32 (as shipped)" +pointcloud,100000,compas_pb_f64,7400123,0.784,0.163579,0.135658,0.332765,0.016538,0.496344,45.239,22.238,61095745,True,True,True,0.0,0.0,"protobuf, double (branch)" diff --git a/benchmarks/serialization/results/pb_precision_compare.html b/benchmarks/serialization/results/pb_precision_compare.html new file mode 100644 index 000000000000..62ed05fbd648 --- /dev/null +++ b/benchmarks/serialization/results/pb_precision_compare.html @@ -0,0 +1,70 @@ +COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:32 · preset quick · repeat 5 · seed 42 · compas compas_pb float32 vs double

json · compact text, losslesscompas_pb_f32 · protobuf, float32 (as shipped)compas_pb_f64 · protobuf, double (branch)

mesh

Round-trip time
1,000 elements
json
5.3 ms
compas_pb_f32
21.6 ms
compas_pb_f64
22.3 ms
10,000 elements
json
62.8 ms
compas_pb_f32
227.5 ms
compas_pb_f64
238.4 ms
Wire size
1,000 elements
json
80.2 KB
compas_pb_f32
181.1 KB
compas_pb_f64
192.8 KB
10,000 elements
json
864.1 KB
compas_pb_f32
1.8 MB
compas_pb_f64
1.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.5 ms3.7 ms5.3 ms21.9681.5 MB0✓ yes
1,000compas_pb_f32181.1 KB0.443×11.5 ms10.1 ms21.6 ms18.321.0 MB1.5e-08✗ no
1,000compas_pb_f64192.8 KB0.416×11.7 ms10.6 ms22.3 ms18.5411.0 MB0✗ no
10,000json864.1 KB1.0×17.0 ms45.8 ms62.8 ms19.31915.3 MB0✓ yes
10,000compas_pb_f321.8 MB0.475×114.2 ms113.3 ms227.5 ms16.44110.2 MB1.5e-08✗ no
10,000compas_pb_f641.9 MB0.446×118.5 ms119.9 ms238.4 ms16.53210.2 MB0✗ no

mesh_attrs

Round-trip time
1,000 elements
json
5.7 ms
compas_pb_f32
26.5 ms
compas_pb_f64
29.3 ms
10,000 elements
json
68.1 ms
compas_pb_f32
277.1 ms
compas_pb_f64
281.1 ms
Wire size
1,000 elements
json
109.5 KB
compas_pb_f32
207.1 KB
compas_pb_f64
218.8 KB
10,000 elements
json
1.1 MB
compas_pb_f32
2.0 MB
compas_pb_f64
2.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms3.8 ms5.7 ms29.3361.6 MB0✓ yes
1,000compas_pb_f32207.1 KB0.529×13.9 ms12.6 ms26.5 ms16.8581.2 MB1.5e-08✗ no
1,000compas_pb_f64218.8 KB0.5×15.3 ms14.0 ms29.3 ms16.0371.2 MB0✗ no
10,000json1.1 MB1.0×20.4 ms47.7 ms68.1 ms24.68415.8 MB0✓ yes
10,000compas_pb_f322.0 MB0.555×144.0 ms133.1 ms277.1 ms15.94412.0 MB1.5e-08✗ no
10,000compas_pb_f642.1 MB0.525×145.1 ms135.9 ms281.1 ms16.49712.0 MB0✗ no

pointcloud

Round-trip time
10,000 elements
json
27.4 ms
compas_pb_f32
44.4 ms
compas_pb_f64
43.2 ms
100,000 elements
json
343.0 ms
compas_pb_f32
493.0 ms
compas_pb_f64
496.3 ms
Wire size
10,000 elements
json
567.0 KB
compas_pb_f32
605.6 KB
compas_pb_f64
722.8 KB
100,000 elements
json
5.5 MB
compas_pb_f32
5.9 MB
compas_pb_f64
7.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.7 ms13.7 ms27.4 ms42.3274.1 MB0✓ yes
10,000compas_pb_f32605.6 KB0.936×16.9 ms27.5 ms44.4 ms22.5745.8 MB3.8e-06✗ no
10,000compas_pb_f64722.8 KB0.785×16.2 ms27.0 ms43.2 ms27.4155.8 MB0✓ yes
100,000json5.5 MB1.0×148.2 ms194.9 ms343.0 ms29.78640.6 MB0✓ yes
100,000compas_pb_f325.9 MB0.936×171.3 ms321.6 ms493.0 ms19.27758.3 MB3.8e-06✗ no
100,000compas_pb_f647.1 MB0.784×163.6 ms332.8 ms496.3 ms22.23858.3 MB0✓ yes
\ No newline at end of file From 6fec8b70650a2d71bf1986ca8f56366f06d20574 Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Fri, 10 Jul 2026 00:45:06 +0200 Subject: [PATCH 05/13] Update serialization benchmarks --- benchmarks/README.md | 98 ++++++++----- benchmarks/serialization/formats.py | 27 +++- benchmarks/serialization/report.py | 136 +++++++++++++++++- .../serialization/results/baseline_quick.csv | 42 +++--- .../serialization/results/baseline_quick.html | 12 +- .../results/baseline_quick_double.csv | 19 --- .../results/baseline_quick_double.html | 70 --------- .../serialization/results/pb_double.csv | 13 -- .../serialization/results/pb_double.html | 70 --------- .../results/pb_precision_compare.csv | 19 --- .../results/pb_precision_compare.html | 70 --------- 11 files changed, 256 insertions(+), 320 deletions(-) delete mode 100644 benchmarks/serialization/results/baseline_quick_double.csv delete mode 100644 benchmarks/serialization/results/baseline_quick_double.html delete mode 100644 benchmarks/serialization/results/pb_double.csv delete mode 100644 benchmarks/serialization/results/pb_double.html delete mode 100644 benchmarks/serialization/results/pb_precision_compare.csv delete mode 100644 benchmarks/serialization/results/pb_precision_compare.html diff --git a/benchmarks/README.md b/benchmarks/README.md index 27d04d9f6e47..795ae5249bf1 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -35,14 +35,14 @@ Registered in [`formats.py`](serialization/formats.py): - `json` — compact text (the default, lossless); - `json_zip` — zip-compressed JSON (size baseline); -- `compas_pb` — protobuf binary via the [`compas_pb`](https://pypi.org/project/compas_pb/) - plugin (optional dep; `pip install compas_pb`). Skipped automatically if not installed. - Currently **float32 → lossy** for float64 geometry; the harness quantifies the error - (see `max_abs_error` / `rms_error`). +- `compas_pb` — protobuf binary via the `compas_pb` plugin (optional dep). We track the + **optimized branch** (`benchmark/double-precision`): double precision, flat packed + coordinate arrays, and inline attribute maps. Skipped automatically if not installed. + The harness still quantifies any residual error (`max_abs_error` / `rms_error`). -Later phases register a `compas_pb` `double` variant and an Arrow/columnar prototype the same -way; the runner picks up any registered, available format automatically and skips those whose -optional dependency is missing (`available=False`). +An Arrow/columnar prototype registers the same way; the runner picks up any registered, +available format automatically and skips those whose optional dependency is missing +(`available=False`). ## Running @@ -67,39 +67,63 @@ Run from the repository root so `benchmarks` imports as a package. Requires a wo ## Results -- `results/baseline_quick.{csv,html}` — JSON, JSON+zip, and `compas_pb` (**as shipped**, - float32) on the quick corpus. Findings: `json_zip` is 2–3.6× smaller than compact JSON - for ~1.5–1.8× slower round-trips; `compas_pb` as-is is **larger and slower than JSON** - and **lossy** (float32), with the error scaling with coordinate magnitude - (mesh ~1.5e-08, pointcloud ~3.8e-06). -- `results/pb_precision_compare.{csv,html}` — **Phase 2 precision probe**: `compas_pb` - float32 vs a `double` build. Double drives coordinate error to **0** and makes - `Pointcloud` fully lossless, for ~+6% (mesh) / ~+19% (pointcloud) wire size. `Mesh` - stays non-lossless even with double — but now purely from **int/float coercion** of - zero-valued `default_vertex_attributes` (magnitude error 0), a defect separate from - precision (PRD §2.2 "Integer coercion"). - -### Reproducing the `double` variant - -The `double` numbers come from an experimental branch of the external `compas_pb` repo, -not the shipped wheel: - -```bash -# in the compas_pb checkout, on a branch: -# flip float -> double in protobuf_defs/compas_pb/generated/geometry.proto (PointData etc.) -# regenerate with the pinned protoc (invocations.PROTOC_VERSION, 31.1): -protoc --proto_path=src/compas_pb/protobuf_defs \ - --python_out=src --pyi_out=src \ - src/compas_pb/protobuf_defs/compas_pb/generated/geometry.proto -pip install -e . # into the compas .venv -python -m benchmarks.serialization.run --formats json compas_pb --out benchmarks/serialization/results/pb_double.csv -pip install --force-reinstall --no-deps compas_pb # restore the as-shipped float32 build -``` +`results/baseline_quick.{csv,html}` — JSON, JSON+zip, and the **optimized** `compas_pb` +(raw and zip-compressed) on the quick corpus. The HTML report opens with an **executive +summary** (headline stat tiles + a per-subject winners table) so the conclusion is visible +before any detail. Headline: with double precision + flat coordinate arrays + inline +attribute maps, `compas_pb` goes from *larger and slower than JSON* (as shipped) to the +**smallest and fastest lossless** option on numeric-heavy data: + +| subject (largest size) | JSON | json_zip | compas_pb | compas_pb_zip | +|---|---|---|---|---| +| mesh @10k, wire | 864 KB | 238 KB | 320 KB | **158 KB** | +| mesh @10k, round-trip | 66 ms | 87 ms | **50 ms** | 58 ms | +| mesh_attrs @10k, wire | 1.1 MB | 339 KB | 651 KB | **273 KB** | +| pointcloud @100k, wire | 5.5 MB | 2.7 MB | 2.3 MB | **2.2 MB** | +| pointcloud @100k, round-trip | 343 ms | 551 ms | **186 ms** | 254 ms | + +All four formats are now **lossless on every subject**. `compas_pb_zip` is smallest; +raw `compas_pb` is fastest (no compress step). Applied optimizations: + +- **Precision fixed** (`float → double`): coordinate error is **0** everywhere. +- **Flat coordinate arrays** replaced a `PointData` message *per vertex/point* (each of + which carried a per-point UUID + name) with packed `repeated double` triplets — the + dominant size/speed win, for Mesh, Pointcloud, Polyline, Polygon, Bezier, Polyhedron. +- **Inline `map` attributes** (Mesh, Graph) dropped the `DictData` + wrapper and skip empty/default entries. +- **Int/float distinction preserved** — `AnyData` gained explicit `int64`/`double` arms + instead of routing numbers through `google.protobuf.Value`, so `0.0` no longer comes + back as `0`. This makes `Mesh`/`Graph` fully lossless (canonical hash matches). +- **CSR face storage** — faces are a flat packed `face_vertices` index array + a + `face_sizes` length array, instead of one `FaceList` message per face. +- **No `Any` wrapper on plain dicts/lists** — `AnyData` gained explicit `dict_value` / + `list_value` arms, so every nested dict/list no longer carries a ~44-byte + `google.protobuf.Any` `type_url`. This cut `mesh_attrs@10k` from **1.1 MB → 651 KB** + (now below JSON) and helps Graph, fallback, and any nested container. + +The optimizations live on the `benchmark/double-precision` branch of the external +`compas_pb` repo (regenerate `_pb2` with the pinned protoc `invocations.PROTOC_VERSION`, +then `pip install -e .` into this `.venv`). + +## Pending optimizations + +1. **Columnar vertex attributes** — `mesh_attrs` is now small but still slower than JSON to + *load* (each vertex rebuilds a `DictData` and repeats the attribute-name string). Storing + attributes column-wise (name once + a packed value array aligned to vertices) is the + Phase-3 columnar layout; it should make attribute-heavy meshes beat JSON on both axes. +2. **Standalone `PointData` guid/name** — still serialized on every standalone Point/Line/ + Frame. Omitting them (design decision: binary parity with JSON vs compactness) would + shrink primitive-heavy payloads. +3. **Graph flat coordinates** — Graph nodes still carry coordinates inside per-node + `AnyData` dicts. A flat node-key + coordinate layout is the analog of the Mesh rewrite, + but node keys are arbitrary so it needs a small schema redesign. ## Status Phase 1: baseline harness + JSON numbers, plus `Data.canonical_hash()` decoupling object identity from the JSON text (`sha256()` is unchanged). -Phase 2 (in progress): `compas_pb` measured; precision fix (double) quantified above. Still -open: the int-coercion fix, a real version-compat policy, and reducing per-type boilerplate. +Phase 2 (in progress): `compas_pb` measured and **optimized** — double precision, flat +coordinate arrays, inline attribute maps, explicit int/float, CSR faces — now a fully +**lossless** binary mode, smaller and faster than JSON on numeric data. Still open: a real +version-compat policy and reducing per-type boilerplate. N1 speed/memory targets for the columnar direction will be set from these baselines. diff --git a/benchmarks/serialization/formats.py b/benchmarks/serialization/formats.py index c9648297a5fa..05e44035e39e 100644 --- a/benchmarks/serialization/formats.py +++ b/benchmarks/serialization/formats.py @@ -10,6 +10,7 @@ """ import io +import zipfile import compas @@ -78,7 +79,8 @@ def _json_zip_loads(blob): # --------------------------------------------------------------------------- -# Protobuf (compas_pb plugin, optional). float32 wire -> lossy for float64 geometry. +# Protobuf (compas_pb plugin, optional). Measured against the optimized branch: +# double precision + flat coordinate arrays + inline attribute maps. # --------------------------------------------------------------------------- try: @@ -101,12 +103,33 @@ def _pb_loads(blob): return pb_load_bts(blob) +def _pb_zip_dumps(obj): + buffer = io.BytesIO() + with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf: + zf.writestr("content.pb", _pb_dumps(obj)) + return buffer.getvalue() + + +def _pb_zip_loads(blob): + with zipfile.ZipFile(io.BytesIO(blob)) as zf: + return _pb_loads(zf.read("content.pb")) + + register( Format( "compas_pb", _pb_dumps, _pb_loads, available=_PB_AVAILABLE, - note="protobuf binary, float32 (lossy)", + note="protobuf binary, double + flat arrays (optimized)", + ) +) +register( + Format( + "compas_pb_zip", + _pb_zip_dumps, + _pb_zip_loads, + available=_PB_AVAILABLE, + note="protobuf binary, zip-compressed", ) ) diff --git a/benchmarks/serialization/report.py b/benchmarks/serialization/report.py index d3acc4be36b5..39850baeb47d 100644 --- a/benchmarks/serialization/report.py +++ b/benchmarks/serialization/report.py @@ -128,6 +128,16 @@ def _css(colors): .badge.ok { color: var(--good); } .badge.no { color: var(--critical); } .note { color: var(--muted); font-size: 12px; } +.summary { margin: 20px 0 8px; } +.takeaway { font-size: 15px; line-height: 1.55; margin: 0 0 18px; color: var(--text-primary); } +.takeaway b { font-weight: 600; } +.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 0 0 20px; } +.tile { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; } +.tile .big { font-size: 26px; font-weight: 650; letter-spacing: -0.01em; } +.tile .lbl { font-size: 12px; color: var(--text-secondary); margin-top: 3px; } +.tile .sub { font-size: 11px; color: var(--muted); margin-top: 1px; } +.win { color: var(--good); font-weight: 600; } +h2.section { margin-top: 8px; } """.replace("%SERIES_LIGHT%", series_light).replace("%SERIES_DARK%", series_dark) @@ -223,6 +233,130 @@ def _table(subject_rows, colors): return '
{}{}
'.format(head, "".join(body)) +def _ratio(x): + return "{:.1f}×".format(x) + + +def _is_lossless(row): + return str(row["lossless"]).lower() in ("true", "1") + + +def _exec_summary(rows, colors, subjects): + """Headline stat tiles + a one-line takeaway + a per-subject winners table. + + Everything is derived from the largest measured size of each subject and expressed + against JSON, so a reader gets the conclusion before any of the detail below. + """ + baseline = "json" + binary = "compas_pb" + per = [] # (subject, size, group_map, smallest_row, fastest_row) + for subj in subjects: + srows = [r for r in rows if r["subject"] == subj] + max_size = max(int(r["size"]) for r in srows) + group = [r for r in srows if int(r["size"]) == max_size] + gmap = {r["format"]: r for r in group} + smallest = min(group, key=lambda r: float(r["size_bytes"])) + fastest = min(group, key=lambda r: float(r["roundtrip_median_s"])) + per.append((subj, max_size, gmap, smallest, fastest)) + + # Tiles: best size / round-trip gains of the binary format vs JSON, and lossless coverage. + size_gain = speed_gain = None + lossless_hits = lossless_total = 0 + for subj, size, gmap, _, _ in per: + if baseline in gmap and binary in gmap: + j, b = gmap[baseline], gmap[binary] + sr = float(j["size_bytes"]) / float(b["size_bytes"]) + spd = float(j["roundtrip_median_s"]) / float(b["roundtrip_median_s"]) + if size_gain is None or sr > size_gain[0]: + size_gain = (sr, subj, size) + if speed_gain is None or spd > speed_gain[0]: + speed_gain = (spd, subj, size) + lossless_total += 1 + lossless_hits += _is_lossless(b) + + tiles = [] + if size_gain: + tiles.append( + '
{r} smaller
' + '
{bin} vs JSON on the wire
' + '
best: {subj} @ {n} elements
'.format( + r=_ratio(size_gain[0]), bin=binary, subj=html.escape(size_gain[1]), n=_fmt_int(size_gain[2]) + ) + ) + if speed_gain: + tiles.append( + '
{r} faster
' + '
{bin} round-trip vs JSON
' + '
best: {subj} @ {n} elements
'.format( + r=_ratio(speed_gain[0]), bin=binary, subj=html.escape(speed_gain[1]), n=_fmt_int(speed_gain[2]) + ) + ) + if lossless_total: + ok = lossless_hits == lossless_total + tiles.append( + '
{h}/{t}
' + '
subjects lossless ({bin})
' + '
exact round-trip of __data__
'.format( + cls=" win" if ok else "", h=lossless_hits, t=lossless_total, bin=binary + ) + ) + + # Winners table: per subject at its largest size, the smallest and fastest format vs JSON. + head = ( + "subjectelementssmallestvs JSON" + "fastest round-tripvs JSON{bin} lossless".format(bin=binary) + ) + body = [] + for subj, size, gmap, smallest, fastest in per: + j = gmap.get(baseline) + size_ratio = "{:.2f}×".format(float(j["size_bytes"]) / float(smallest["size_bytes"])) if j else "—" + speed_ratio = "{:.2f}×".format(float(j["roundtrip_median_s"]) / float(fastest["roundtrip_median_s"])) if j else "—" + b = gmap.get(binary) + badge = ( + ('✓ yes' if _is_lossless(b) else '✗ no') + if b + else '' + ) + body.append( + "{subj}{n}" + '{sf} · {sb}{sr}' + '{ff} · {ft}{spr}' + "{badge}".format( + subj=html.escape(subj), + n=_fmt_int(size), + s1=_slot(colors, smallest["format"]), + sf=html.escape(smallest["format"]), + sb=_fmt_bytes(smallest["size_bytes"]), + sr=size_ratio, + s2=_slot(colors, fastest["format"]), + ff=html.escape(fastest["format"]), + ft=_fmt_time(fastest["roundtrip_median_s"]), + spr=speed_ratio, + badge=badge, + ) + ) + + takeaway = "" + if size_gain and speed_gain: + takeaway = ( + '

On the largest payloads, {bin} (protobuf: double + flat ' + "coordinate arrays) is the smallest and fastest option — up to {sr} smaller and " + "{spd} faster to load than compact JSON, {loss}.

".format( + bin=binary, + sr=_ratio(size_gain[0]), + spd=_ratio(speed_gain[0]), + loss=("losslessly" if lossless_hits == lossless_total else "with remaining fidelity notes below"), + ) + ) + + return ( + '

Summary

' + + takeaway + + '
{}
'.format("".join(tiles)) + + '
{}{}
'.format(head, "".join(body)) + ) + + def build_html(rows, meta=None): """Return a full standalone HTML document for the given result rows. @@ -250,7 +384,7 @@ def build_html(rows, meta=None): if key in meta: meta_bits.append("{} {}".format(key, meta[key])) - sections = [_legend(rows, colors)] + sections = [_exec_summary(rows, colors, subjects), _legend(rows, colors)] for subject in subjects: subject_rows = [r for r in rows if r["subject"] == subject] sections.append("

{}

".format(html.escape(subject))) diff --git a/benchmarks/serialization/results/baseline_quick.csv b/benchmarks/serialization/results/baseline_quick.csv index 46eab0f83db4..cf9d8dc24e6a 100644 --- a/benchmarks/serialization/results/baseline_quick.csv +++ b/benchmarks/serialization/results/baseline_quick.csv @@ -1,19 +1,25 @@ subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -mesh,1000,json,82154,1.0,0.001583,7.3e-05,0.003765,0.000142,0.005348,51.891,21.821,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,json_zip,28052,2.929,0.003662,0.000222,0.003998,0.002349,0.00766,7.66,7.017,1615288,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,1000,compas_pb,185410,0.443,0.011866,0.008271,0.010729,0.00013,0.022596,15.625,17.281,1087150,False,False,False,1.4882048593456432e-08,2.5012009156355184e-09,"protobuf binary, float32 (lossy)" -mesh,10000,json,884888,1.0,0.019261,0.003012,0.052553,0.004602,0.071813,45.943,16.838,16027677,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,json_zip,243863,3.629,0.041683,0.002839,0.051803,0.005303,0.093486,5.85,4.708,16031054,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,10000,compas_pb,1862921,0.475,0.120204,0.002367,0.116941,0.004491,0.237145,15.498,15.93,10663623,False,False,False,1.4897168276739592e-08,2.4472232123975927e-09,"protobuf binary, float32 (lossy)" -mesh_attrs,1000,json,112098,1.0,0.001904,8.3e-05,0.00397,6.7e-05,0.005874,58.861,28.24,1666431,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,json_zip,38107,2.942,0.004875,6.7e-05,0.004451,0.000131,0.009326,7.817,8.562,1669264,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,1000,compas_pb,212034,0.529,0.015673,0.000478,0.013273,0.00063,0.028946,13.529,15.975,1279505,False,False,False,1.4882048593456432e-08,2.3344579357147124e-09,"protobuf binary, float32 (lossy)" -mesh_attrs,10000,json,1177508,1.0,0.022233,0.002673,0.050886,0.003608,0.073119,52.962,23.14,16560353,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,json_zip,347077,3.393,0.052582,0.003093,0.054935,0.005467,0.107517,6.601,6.318,16563482,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,10000,compas_pb,2122924,0.555,0.150893,0.00196,0.140561,0.006571,0.291453,14.069,15.103,12576001,False,False,False,1.4897168276739592e-08,2.2875342499681117e-09,"protobuf binary, float32 (lossy)" -pointcloud,10000,json,580633,1.0,0.014534,0.00012,0.014743,0.003123,0.029277,39.95,39.384,4261534,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,json_zip,280728,2.068,0.0367,0.004352,0.015156,0.003125,0.051855,7.649,18.523,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,10000,compas_pb,620120,0.936,0.018244,0.015125,0.028057,0.004947,0.046301,33.991,22.102,6113793,False,False,False,3.814631440945959e-06,1.4766756134925858e-06,"protobuf binary, float32 (lossy)" -pointcloud,100000,json,5804860,1.0,0.161026,0.004842,0.234024,0.021323,0.39505,36.049,24.805,42597425,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,json_zip,2792759,2.079,0.374419,0.007617,0.218703,0.018553,0.593123,7.459,12.77,42604858,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,100000,compas_pb,6200123,0.936,0.168653,0.13468,0.333715,0.014011,0.502368,36.763,18.579,61095745,False,False,False,3.8146725387377955e-06,1.4802791418516803e-06,"protobuf binary, float32 (lossy)" +mesh,1000,json,82154,1.0,0.001566,8.3e-05,0.003726,0.000121,0.005292,52.457,22.047,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,json_zip,28052,2.929,0.003475,9e-05,0.003789,0.001924,0.007265,8.071,7.403,1615280,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,1000,compas_pb,32957,2.493,0.00162,0.007135,0.00338,7.8e-05,0.005,20.344,9.75,870324,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,1000,compas_pb_zip,16376,5.017,0.002084,5.1e-05,0.003331,3e-06,0.005415,7.856,4.917,904677,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,10000,json,884888,1.0,0.016789,0.002451,0.045899,0.003391,0.062688,52.708,19.279,16027789,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,json_zip,243864,3.629,0.038994,0.002556,0.047277,0.003323,0.08627,6.254,5.158,16030454,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,10000,compas_pb,328068,2.697,0.015875,9.9e-05,0.033815,0.004066,0.04969,20.666,9.702,8632468,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,10000,compas_pb_zip,162321,5.451,0.022556,0.000355,0.034286,0.003739,0.056843,7.196,4.734,8962740,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,1000,json,112098,1.0,0.001881,7.1e-05,0.003836,0.002122,0.005718,59.583,29.221,1666239,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,json_zip,38109,2.942,0.00433,0.000105,0.003878,8.9e-05,0.008208,8.801,9.826,1669104,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,1000,compas_pb,66663,1.682,0.005835,0.000327,0.006685,0.00019,0.01252,11.426,9.972,1281853,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,1000,compas_pb_zip,28365,3.952,0.006733,9.7e-05,0.006929,6.6e-05,0.013662,4.213,4.094,1347488,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,10000,json,1177508,1.0,0.021072,0.002351,0.047697,0.003086,0.068769,55.881,24.687,16560353,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,json_zip,347074,3.393,0.051664,0.003469,0.047957,0.004089,0.099621,6.718,7.237,16567738,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,10000,compas_pb,666958,1.765,0.05772,0.001917,0.07199,0.005181,0.12971,11.555,9.265,12575853,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,10000,compas_pb_zip,279834,4.208,0.069739,0.000465,0.073197,0.003803,0.142936,4.013,3.823,13245015,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,10000,json,580633,1.0,0.013699,0.000116,0.014419,0.002765,0.028118,42.385,40.269,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,json_zip,280725,2.068,0.033433,0.002402,0.014345,0.00249,0.047778,8.397,19.57,4269071,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,10000,compas_pb,240124,2.418,0.003262,3.9e-05,0.010587,0.002621,0.013849,73.603,22.682,3599513,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,10000,compas_pb_zip,228837,2.537,0.009202,7.7e-05,0.010907,0.002296,0.02011,24.868,20.98,3840761,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,100000,json,5804860,1.0,0.150237,0.004721,0.186795,0.017851,0.337033,38.638,31.076,42597425,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,json_zip,2792760,2.079,0.348003,0.009456,0.180972,0.028574,0.528974,8.025,15.432,42604858,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,100000,compas_pb,2400128,2.419,0.032329,0.00067,0.15471,0.00788,0.187039,74.241,15.514,35996537,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,100000,compas_pb_zip,2286081,2.539,0.093947,0.000508,0.164759,0.019508,0.258705,24.334,13.875,38392481,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" diff --git a/benchmarks/serialization/results/baseline_quick.html b/benchmarks/serialization/results/baseline_quick.html index 6d50c3405141..891c42370f33 100644 --- a/benchmarks/serialization/results/baseline_quick.html +++ b/benchmarks/serialization/results/baseline_quick.html @@ -67,4 +67,14 @@ .badge.ok { color: var(--good); } .badge.no { color: var(--critical); } .note { color: var(--muted); font-size: 12px; } -

COMPAS serialization benchmark

generated 2026-07-09 18:34 · preset quick · repeat 5 · seed 42 · compas 2.15.0-e03e4097

json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, float32 (lossy)

mesh

Round-trip time
1,000 elements
json
5.3 ms
json_zip
7.7 ms
compas_pb
22.6 ms
10,000 elements
json
71.8 ms
json_zip
93.5 ms
compas_pb
237.1 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
181.1 KB
10,000 elements
json
864.1 KB
json_zip
238.1 KB
compas_pb
1.8 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.8 ms5.3 ms21.8211.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.7 ms4.0 ms7.7 ms7.0171.5 MB0✓ yes
1,000compas_pb181.1 KB0.443×11.9 ms10.7 ms22.6 ms17.2811.0 MB1.5e-08✗ no
10,000json864.1 KB1.0×19.3 ms52.6 ms71.8 ms16.83815.3 MB0✓ yes
10,000json_zip238.1 KB3.629×41.7 ms51.8 ms93.5 ms4.70815.3 MB0✓ yes
10,000compas_pb1.8 MB0.475×120.2 ms116.9 ms237.1 ms15.9310.2 MB1.5e-08✗ no

mesh_attrs

Round-trip time
1,000 elements
json
5.9 ms
json_zip
9.3 ms
compas_pb
28.9 ms
10,000 elements
json
73.1 ms
json_zip
107.5 ms
compas_pb
291.5 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
207.1 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
2.0 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms4.0 ms5.9 ms28.241.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.9 ms4.5 ms9.3 ms8.5621.6 MB0✓ yes
1,000compas_pb207.1 KB0.529×15.7 ms13.3 ms28.9 ms15.9751.2 MB1.5e-08✗ no
10,000json1.1 MB1.0×22.2 ms50.9 ms73.1 ms23.1415.8 MB0✓ yes
10,000json_zip338.9 KB3.393×52.6 ms54.9 ms107.5 ms6.31815.8 MB0✓ yes
10,000compas_pb2.0 MB0.555×150.9 ms140.6 ms291.5 ms15.10312.0 MB1.5e-08✗ no

pointcloud

Round-trip time
10,000 elements
json
29.3 ms
json_zip
51.9 ms
compas_pb
46.3 ms
100,000 elements
json
395.1 ms
json_zip
593.1 ms
compas_pb
502.4 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
605.6 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
5.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×14.5 ms14.7 ms29.3 ms39.3844.1 MB0✓ yes
10,000json_zip274.1 KB2.068×36.7 ms15.2 ms51.9 ms18.5234.1 MB0✓ yes
10,000compas_pb605.6 KB0.936×18.2 ms28.1 ms46.3 ms22.1025.8 MB3.8e-06✗ no
100,000json5.5 MB1.0×161.0 ms234.0 ms395.1 ms24.80540.6 MB0✓ yes
100,000json_zip2.7 MB2.079×374.4 ms218.7 ms593.1 ms12.7740.6 MB0✓ yes
100,000compas_pb5.9 MB0.936×168.7 ms333.7 ms502.4 ms18.57958.3 MB3.8e-06✗ no
\ No newline at end of file +.summary { margin: 20px 0 8px; } +.takeaway { font-size: 15px; line-height: 1.55; margin: 0 0 18px; color: var(--text-primary); } +.takeaway b { font-weight: 600; } +.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 0 0 20px; } +.tile { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; } +.tile .big { font-size: 26px; font-weight: 650; letter-spacing: -0.01em; } +.tile .lbl { font-size: 12px; color: var(--text-secondary); margin-top: 3px; } +.tile .sub { font-size: 11px; color: var(--muted); margin-top: 1px; } +.win { color: var(--good); font-weight: 600; } +h2.section { margin-top: 8px; } +

COMPAS serialization benchmark

generated 2026-07-10 00:41 · preset quick · repeat 5 · seed 42 · compas 2.15.0-b26fd518

Summary

On the largest payloads, compas_pb (protobuf: double + flat coordinate arrays) is the smallest and fastest option — up to 2.7× smaller and 1.8× faster to load than compact JSON, losslessly.

2.7× smaller
compas_pb vs JSON on the wire
best: mesh @ 10,000 elements
1.8× faster
compas_pb round-trip vs JSON
best: pointcloud @ 100,000 elements
3/3
subjects lossless (compas_pb)
exact round-trip of __data__
subjectelementssmallestvs JSONfastest round-tripvs JSONcompas_pb lossless
mesh10,000compas_pb_zip · 158.5 KB5.45×compas_pb · 49.7 ms1.26×✓ yes
mesh_attrs10,000compas_pb_zip · 273.3 KB4.21×json · 68.8 ms1.00×✓ yes
pointcloud100,000compas_pb_zip · 2.2 MB2.54×compas_pb · 187.0 ms1.80×✓ yes
json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, double + flat arrays (optimized)compas_pb_zip · protobuf binary, zip-compressed

mesh

Round-trip time
1,000 elements
json
5.3 ms
json_zip
7.3 ms
compas_pb
5.0 ms
compas_pb_zip
5.4 ms
10,000 elements
json
62.7 ms
json_zip
86.3 ms
compas_pb
49.7 ms
compas_pb_zip
56.8 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
32.2 KB
compas_pb_zip
16.0 KB
10,000 elements
json
864.1 KB
json_zip
238.1 KB
compas_pb
320.4 KB
compas_pb_zip
158.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.7 ms5.3 ms22.0471.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.5 ms3.8 ms7.3 ms7.4031.5 MB0✓ yes
1,000compas_pb32.2 KB2.493×1.6 ms3.4 ms5.0 ms9.75849.9 KB0✓ yes
1,000compas_pb_zip16.0 KB5.017×2.1 ms3.3 ms5.4 ms4.917883.5 KB0✓ yes
10,000json864.1 KB1.0×16.8 ms45.9 ms62.7 ms19.27915.3 MB0✓ yes
10,000json_zip238.1 KB3.629×39.0 ms47.3 ms86.3 ms5.15815.3 MB0✓ yes
10,000compas_pb320.4 KB2.697×15.9 ms33.8 ms49.7 ms9.7028.2 MB0✓ yes
10,000compas_pb_zip158.5 KB5.451×22.6 ms34.3 ms56.8 ms4.7348.5 MB0✓ yes

mesh_attrs

Round-trip time
1,000 elements
json
5.7 ms
json_zip
8.2 ms
compas_pb
12.5 ms
compas_pb_zip
13.7 ms
10,000 elements
json
68.8 ms
json_zip
99.6 ms
compas_pb
129.7 ms
compas_pb_zip
142.9 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
65.1 KB
compas_pb_zip
27.7 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
651.3 KB
compas_pb_zip
273.3 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms3.8 ms5.7 ms29.2211.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.3 ms3.9 ms8.2 ms9.8261.6 MB0✓ yes
1,000compas_pb65.1 KB1.682×5.8 ms6.7 ms12.5 ms9.9721.2 MB0✓ yes
1,000compas_pb_zip27.7 KB3.952×6.7 ms6.9 ms13.7 ms4.0941.3 MB0✓ yes
10,000json1.1 MB1.0×21.1 ms47.7 ms68.8 ms24.68715.8 MB0✓ yes
10,000json_zip338.9 KB3.393×51.7 ms48.0 ms99.6 ms7.23715.8 MB0✓ yes
10,000compas_pb651.3 KB1.765×57.7 ms72.0 ms129.7 ms9.26512.0 MB0✓ yes
10,000compas_pb_zip273.3 KB4.208×69.7 ms73.2 ms142.9 ms3.82312.6 MB0✓ yes

pointcloud

Round-trip time
10,000 elements
json
28.1 ms
json_zip
47.8 ms
compas_pb
13.8 ms
compas_pb_zip
20.1 ms
100,000 elements
json
337.0 ms
json_zip
529.0 ms
compas_pb
187.0 ms
compas_pb_zip
258.7 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
234.5 KB
compas_pb_zip
223.5 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
2.3 MB
compas_pb_zip
2.2 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.7 ms14.4 ms28.1 ms40.2694.1 MB0✓ yes
10,000json_zip274.1 KB2.068×33.4 ms14.3 ms47.8 ms19.574.1 MB0✓ yes
10,000compas_pb234.5 KB2.418×3.3 ms10.6 ms13.8 ms22.6823.4 MB0✓ yes
10,000compas_pb_zip223.5 KB2.537×9.2 ms10.9 ms20.1 ms20.983.7 MB0✓ yes
100,000json5.5 MB1.0×150.2 ms186.8 ms337.0 ms31.07640.6 MB0✓ yes
100,000json_zip2.7 MB2.079×348.0 ms181.0 ms529.0 ms15.43240.6 MB0✓ yes
100,000compas_pb2.3 MB2.419×32.3 ms154.7 ms187.0 ms15.51434.3 MB0✓ yes
100,000compas_pb_zip2.2 MB2.539×93.9 ms164.8 ms258.7 ms13.87536.6 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/results/baseline_quick_double.csv b/benchmarks/serialization/results/baseline_quick_double.csv deleted file mode 100644 index 228447e036a8..000000000000 --- a/benchmarks/serialization/results/baseline_quick_double.csv +++ /dev/null @@ -1,19 +0,0 @@ -subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -mesh,1000,json,82154,1.0,0.001567,9e-05,0.003719,8.2e-05,0.005287,52.418,22.088,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,json_zip,28049,2.929,0.003484,0.000134,0.004413,0.003348,0.007897,8.05,6.356,1615288,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,1000,compas_pb,197442,0.416,0.012311,0.008889,0.010525,0.000287,0.022835,16.038,18.76,1086758,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -mesh,10000,json,884888,1.0,0.0184,0.00301,0.048039,0.003817,0.066439,48.093,18.42,16027677,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,json_zip,243868,3.629,0.04081,0.002845,0.048154,0.003762,0.088964,5.976,5.064,16031062,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,10000,compas_pb,1982121,0.446,0.117473,0.003334,0.116975,0.005821,0.234448,16.873,16.945,10663259,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -mesh_attrs,1000,json,112098,1.0,0.001941,0.000164,0.004592,0.00053,0.006532,57.759,24.413,1666431,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,json_zip,38109,2.942,0.00545,0.00053,0.004582,0.000389,0.010031,6.993,8.318,1669256,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,1000,compas_pb,224066,0.5,0.015172,0.000624,0.013195,0.000381,0.028367,14.768,16.982,1279505,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -mesh_attrs,10000,json,1177508,1.0,0.022469,0.002624,0.051467,0.004636,0.073937,52.405,22.879,16560353,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,json_zip,347079,3.393,0.05392,0.004,0.053599,0.005939,0.107519,6.437,6.475,16563482,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,10000,compas_pb,2242124,0.525,0.144902,0.001894,0.136261,0.004908,0.281164,15.473,16.455,12576001,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -pointcloud,10000,json,580633,1.0,0.014378,0.000746,0.014751,0.002958,0.029129,40.384,39.363,4261534,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,json_zip,280725,2.068,0.03434,0.002842,0.014972,0.00311,0.049311,8.175,18.75,4264079,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,10000,compas_pb,740120,0.785,0.016721,0.014406,0.02714,0.004643,0.043861,44.264,27.27,6113793,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" -pointcloud,100000,json,5804860,1.0,0.155892,0.001105,0.208787,0.017486,0.364679,37.236,27.803,42597425,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,json_zip,2792754,2.079,0.36917,0.004919,0.217333,0.019755,0.586503,7.565,12.85,42604858,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,100000,compas_pb,7400123,0.784,0.163784,0.131419,0.320664,0.014701,0.484448,45.182,23.078,61095745,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" diff --git a/benchmarks/serialization/results/baseline_quick_double.html b/benchmarks/serialization/results/baseline_quick_double.html deleted file mode 100644 index 57138c1c901c..000000000000 --- a/benchmarks/serialization/results/baseline_quick_double.html +++ /dev/null @@ -1,70 +0,0 @@ -COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:42 · preset quick · repeat 5 · seed 42 · compas 2.15.0-e03e4097

json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, float32 (lossy)

mesh

Round-trip time
1,000 elements
json
5.3 ms
json_zip
7.9 ms
compas_pb
22.8 ms
10,000 elements
json
66.4 ms
json_zip
89.0 ms
compas_pb
234.4 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
192.8 KB
10,000 elements
json
864.1 KB
json_zip
238.2 KB
compas_pb
1.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.7 ms5.3 ms22.0881.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.5 ms4.4 ms7.9 ms6.3561.5 MB0✓ yes
1,000compas_pb192.8 KB0.416×12.3 ms10.5 ms22.8 ms18.761.0 MB0✗ no
10,000json864.1 KB1.0×18.4 ms48.0 ms66.4 ms18.4215.3 MB0✓ yes
10,000json_zip238.2 KB3.629×40.8 ms48.2 ms89.0 ms5.06415.3 MB0✓ yes
10,000compas_pb1.9 MB0.446×117.5 ms117.0 ms234.4 ms16.94510.2 MB0✗ no

mesh_attrs

Round-trip time
1,000 elements
json
6.5 ms
json_zip
10.0 ms
compas_pb
28.4 ms
10,000 elements
json
73.9 ms
json_zip
107.5 ms
compas_pb
281.2 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
218.8 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
2.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms4.6 ms6.5 ms24.4131.6 MB0✓ yes
1,000json_zip37.2 KB2.942×5.5 ms4.6 ms10.0 ms8.3181.6 MB0✓ yes
1,000compas_pb218.8 KB0.5×15.2 ms13.2 ms28.4 ms16.9821.2 MB0✗ no
10,000json1.1 MB1.0×22.5 ms51.5 ms73.9 ms22.87915.8 MB0✓ yes
10,000json_zip338.9 KB3.393×53.9 ms53.6 ms107.5 ms6.47515.8 MB0✓ yes
10,000compas_pb2.1 MB0.525×144.9 ms136.3 ms281.2 ms16.45512.0 MB0✗ no

pointcloud

Round-trip time
10,000 elements
json
29.1 ms
json_zip
49.3 ms
compas_pb
43.9 ms
100,000 elements
json
364.7 ms
json_zip
586.5 ms
compas_pb
484.4 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
722.8 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
7.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×14.4 ms14.8 ms29.1 ms39.3634.1 MB0✓ yes
10,000json_zip274.1 KB2.068×34.3 ms15.0 ms49.3 ms18.754.1 MB0✓ yes
10,000compas_pb722.8 KB0.785×16.7 ms27.1 ms43.9 ms27.275.8 MB0✓ yes
100,000json5.5 MB1.0×155.9 ms208.8 ms364.7 ms27.80340.6 MB0✓ yes
100,000json_zip2.7 MB2.079×369.2 ms217.3 ms586.5 ms12.8540.6 MB0✓ yes
100,000compas_pb7.1 MB0.784×163.8 ms320.7 ms484.4 ms23.07858.3 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/results/pb_double.csv b/benchmarks/serialization/results/pb_double.csv deleted file mode 100644 index 8104f510b635..000000000000 --- a/benchmarks/serialization/results/pb_double.csv +++ /dev/null @@ -1,13 +0,0 @@ -subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -mesh,1000,json,82154,1.0,0.001589,9.4e-05,0.003713,0.000104,0.005302,51.694,22.128,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,compas_pb,197442,0.416,0.011683,0.007519,0.010649,0.002442,0.022332,16.9,18.541,1087122,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -mesh,10000,json,884888,1.0,0.018243,0.003325,0.048497,0.005433,0.06674,48.506,18.246,16028133,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,compas_pb,1982121,0.446,0.118464,0.001636,0.119897,0.007634,0.238361,16.732,16.532,10663371,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -mesh_attrs,1000,json,112098,1.0,0.001899,5.2e-05,0.003945,0.00026,0.005844,59.043,28.413,1666239,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,compas_pb,224066,0.5,0.015348,0.000632,0.013972,0.006161,0.02932,14.599,16.037,1279505,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -mesh_attrs,10000,json,1177508,1.0,0.021897,0.002534,0.050358,0.004144,0.072255,53.774,23.383,16560465,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,compas_pb,2242124,0.525,0.145139,0.002585,0.135914,0.006323,0.281053,15.448,16.497,12576001,False,True,False,0.0,0.0,"protobuf binary, float32 (lossy)" -pointcloud,10000,json,580633,1.0,0.014235,0.00017,0.014198,0.003257,0.028433,40.789,40.897,4261534,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,compas_pb,740120,0.785,0.016236,0.012043,0.026997,0.004063,0.043233,45.586,27.415,6114057,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" -pointcloud,100000,json,5804860,1.0,0.155184,0.001999,0.200165,0.008131,0.355349,37.406,29.0,42597425,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,compas_pb,7400123,0.784,0.163579,0.135658,0.332765,0.016538,0.496344,45.239,22.238,61095745,True,True,True,0.0,0.0,"protobuf binary, float32 (lossy)" diff --git a/benchmarks/serialization/results/pb_double.html b/benchmarks/serialization/results/pb_double.html deleted file mode 100644 index 978bd6cb7a7c..000000000000 --- a/benchmarks/serialization/results/pb_double.html +++ /dev/null @@ -1,70 +0,0 @@ -COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:28 · preset quick · repeat 5 · seed 42 · compas 2.15.0-e03e4097

json · compact text, losslesscompas_pb · protobuf binary, float32 (lossy)

mesh

Round-trip time
1,000 elements
json
5.3 ms
compas_pb
22.3 ms
10,000 elements
json
66.7 ms
compas_pb
238.4 ms
Wire size
1,000 elements
json
80.2 KB
compas_pb
192.8 KB
10,000 elements
json
864.1 KB
compas_pb
1.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.7 ms5.3 ms22.1281.5 MB0✓ yes
1,000compas_pb192.8 KB0.416×11.7 ms10.6 ms22.3 ms18.5411.0 MB0✗ no
10,000json864.1 KB1.0×18.2 ms48.5 ms66.7 ms18.24615.3 MB0✓ yes
10,000compas_pb1.9 MB0.446×118.5 ms119.9 ms238.4 ms16.53210.2 MB0✗ no

mesh_attrs

Round-trip time
1,000 elements
json
5.8 ms
compas_pb
29.3 ms
10,000 elements
json
72.3 ms
compas_pb
281.1 ms
Wire size
1,000 elements
json
109.5 KB
compas_pb
218.8 KB
10,000 elements
json
1.1 MB
compas_pb
2.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms3.9 ms5.8 ms28.4131.6 MB0✓ yes
1,000compas_pb218.8 KB0.5×15.3 ms14.0 ms29.3 ms16.0371.2 MB0✗ no
10,000json1.1 MB1.0×21.9 ms50.4 ms72.3 ms23.38315.8 MB0✓ yes
10,000compas_pb2.1 MB0.525×145.1 ms135.9 ms281.1 ms16.49712.0 MB0✗ no

pointcloud

Round-trip time
10,000 elements
json
28.4 ms
compas_pb
43.2 ms
100,000 elements
json
355.3 ms
compas_pb
496.3 ms
Wire size
10,000 elements
json
567.0 KB
compas_pb
722.8 KB
100,000 elements
json
5.5 MB
compas_pb
7.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×14.2 ms14.2 ms28.4 ms40.8974.1 MB0✓ yes
10,000compas_pb722.8 KB0.785×16.2 ms27.0 ms43.2 ms27.4155.8 MB0✓ yes
100,000json5.5 MB1.0×155.2 ms200.2 ms355.3 ms29.040.6 MB0✓ yes
100,000compas_pb7.1 MB0.784×163.6 ms332.8 ms496.3 ms22.23858.3 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/results/pb_precision_compare.csv b/benchmarks/serialization/results/pb_precision_compare.csv deleted file mode 100644 index 0ec2ed325f45..000000000000 --- a/benchmarks/serialization/results/pb_precision_compare.csv +++ /dev/null @@ -1,19 +0,0 @@ -subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -mesh,1000,json,82154,1.0,0.001516,0.000129,0.00374,0.000119,0.005256,54.181,21.968,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,compas_pb_f32,185410,0.443,0.011516,0.010525,0.010121,0.000869,0.021637,16.1,18.32,1086926,False,False,False,1.4882048593456432e-08,2.5012009156355184e-09,"protobuf, float32 (as shipped)" -mesh,1000,compas_pb_f64,197442,0.416,0.011683,0.007519,0.010649,0.002442,0.022332,16.9,18.541,1087122,False,True,False,0.0,0.0,"protobuf, double (branch)" -mesh,10000,json,884888,1.0,0.016997,0.003222,0.045805,0.003729,0.062802,52.062,19.319,16027677,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,compas_pb_f32,1862921,0.475,0.114164,0.001157,0.113307,0.003653,0.227471,16.318,16.441,10663651,False,False,False,1.4897168276739592e-08,2.4472232123975927e-09,"protobuf, float32 (as shipped)" -mesh,10000,compas_pb_f64,1982121,0.446,0.118464,0.001636,0.119897,0.007634,0.238361,16.732,16.532,10663371,False,True,False,0.0,0.0,"protobuf, double (branch)" -mesh_attrs,1000,json,112098,1.0,0.001879,3.7e-05,0.003821,3.7e-05,0.0057,59.668,29.336,1666431,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,compas_pb_f32,212034,0.529,0.013908,6.4e-05,0.012577,0.000185,0.026486,15.245,16.858,1279505,False,False,False,1.4882048593456432e-08,2.3344579357147124e-09,"protobuf, float32 (as shipped)" -mesh_attrs,1000,compas_pb_f64,224066,0.5,0.015348,0.000632,0.013972,0.006161,0.02932,14.599,16.037,1279505,False,True,False,0.0,0.0,"protobuf, double (branch)" -mesh_attrs,10000,json,1177508,1.0,0.020361,0.002154,0.047704,0.005262,0.068064,57.833,24.684,16560353,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,compas_pb_f32,2122924,0.555,0.143979,0.001996,0.133149,0.004651,0.277128,14.745,15.944,12576001,False,False,False,1.4897168276739592e-08,2.2875342499681117e-09,"protobuf, float32 (as shipped)" -mesh_attrs,10000,compas_pb_f64,2242124,0.525,0.145139,0.002585,0.135914,0.006323,0.281053,15.448,16.497,12576001,False,True,False,0.0,0.0,"protobuf, double (branch)" -pointcloud,10000,json,580633,1.0,0.013667,0.000176,0.013718,0.002513,0.027384,42.485,42.327,4261476,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,compas_pb_f32,620120,0.936,0.016915,0.013203,0.02747,0.003954,0.044385,36.662,22.574,6113793,False,False,False,3.814631440945959e-06,1.4766756134925858e-06,"protobuf, float32 (as shipped)" -pointcloud,10000,compas_pb_f64,740120,0.785,0.016236,0.012043,0.026997,0.004063,0.043233,45.586,27.415,6114057,True,True,True,0.0,0.0,"protobuf, double (branch)" -pointcloud,100000,json,5804860,1.0,0.14816,0.001288,0.194884,0.015763,0.343044,39.18,29.786,42597367,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,compas_pb_f32,6200123,0.936,0.171329,0.1231,0.321633,0.015959,0.492962,36.188,19.277,61095745,False,False,False,3.8146725387377955e-06,1.4802791418516803e-06,"protobuf, float32 (as shipped)" -pointcloud,100000,compas_pb_f64,7400123,0.784,0.163579,0.135658,0.332765,0.016538,0.496344,45.239,22.238,61095745,True,True,True,0.0,0.0,"protobuf, double (branch)" diff --git a/benchmarks/serialization/results/pb_precision_compare.html b/benchmarks/serialization/results/pb_precision_compare.html deleted file mode 100644 index 62ed05fbd648..000000000000 --- a/benchmarks/serialization/results/pb_precision_compare.html +++ /dev/null @@ -1,70 +0,0 @@ -COMPAS serialization benchmark

COMPAS serialization benchmark

generated 2026-07-09 18:32 · preset quick · repeat 5 · seed 42 · compas compas_pb float32 vs double

json · compact text, losslesscompas_pb_f32 · protobuf, float32 (as shipped)compas_pb_f64 · protobuf, double (branch)

mesh

Round-trip time
1,000 elements
json
5.3 ms
compas_pb_f32
21.6 ms
compas_pb_f64
22.3 ms
10,000 elements
json
62.8 ms
compas_pb_f32
227.5 ms
compas_pb_f64
238.4 ms
Wire size
1,000 elements
json
80.2 KB
compas_pb_f32
181.1 KB
compas_pb_f64
192.8 KB
10,000 elements
json
864.1 KB
compas_pb_f32
1.8 MB
compas_pb_f64
1.9 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.5 ms3.7 ms5.3 ms21.9681.5 MB0✓ yes
1,000compas_pb_f32181.1 KB0.443×11.5 ms10.1 ms21.6 ms18.321.0 MB1.5e-08✗ no
1,000compas_pb_f64192.8 KB0.416×11.7 ms10.6 ms22.3 ms18.5411.0 MB0✗ no
10,000json864.1 KB1.0×17.0 ms45.8 ms62.8 ms19.31915.3 MB0✓ yes
10,000compas_pb_f321.8 MB0.475×114.2 ms113.3 ms227.5 ms16.44110.2 MB1.5e-08✗ no
10,000compas_pb_f641.9 MB0.446×118.5 ms119.9 ms238.4 ms16.53210.2 MB0✗ no

mesh_attrs

Round-trip time
1,000 elements
json
5.7 ms
compas_pb_f32
26.5 ms
compas_pb_f64
29.3 ms
10,000 elements
json
68.1 ms
compas_pb_f32
277.1 ms
compas_pb_f64
281.1 ms
Wire size
1,000 elements
json
109.5 KB
compas_pb_f32
207.1 KB
compas_pb_f64
218.8 KB
10,000 elements
json
1.1 MB
compas_pb_f32
2.0 MB
compas_pb_f64
2.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms3.8 ms5.7 ms29.3361.6 MB0✓ yes
1,000compas_pb_f32207.1 KB0.529×13.9 ms12.6 ms26.5 ms16.8581.2 MB1.5e-08✗ no
1,000compas_pb_f64218.8 KB0.5×15.3 ms14.0 ms29.3 ms16.0371.2 MB0✗ no
10,000json1.1 MB1.0×20.4 ms47.7 ms68.1 ms24.68415.8 MB0✓ yes
10,000compas_pb_f322.0 MB0.555×144.0 ms133.1 ms277.1 ms15.94412.0 MB1.5e-08✗ no
10,000compas_pb_f642.1 MB0.525×145.1 ms135.9 ms281.1 ms16.49712.0 MB0✗ no

pointcloud

Round-trip time
10,000 elements
json
27.4 ms
compas_pb_f32
44.4 ms
compas_pb_f64
43.2 ms
100,000 elements
json
343.0 ms
compas_pb_f32
493.0 ms
compas_pb_f64
496.3 ms
Wire size
10,000 elements
json
567.0 KB
compas_pb_f32
605.6 KB
compas_pb_f64
722.8 KB
100,000 elements
json
5.5 MB
compas_pb_f32
5.9 MB
compas_pb_f64
7.1 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.7 ms13.7 ms27.4 ms42.3274.1 MB0✓ yes
10,000compas_pb_f32605.6 KB0.936×16.9 ms27.5 ms44.4 ms22.5745.8 MB3.8e-06✗ no
10,000compas_pb_f64722.8 KB0.785×16.2 ms27.0 ms43.2 ms27.4155.8 MB0✓ yes
100,000json5.5 MB1.0×148.2 ms194.9 ms343.0 ms29.78640.6 MB0✓ yes
100,000compas_pb_f325.9 MB0.936×171.3 ms321.6 ms493.0 ms19.27758.3 MB3.8e-06✗ no
100,000compas_pb_f647.1 MB0.784×163.6 ms332.8 ms496.3 ms22.23858.3 MB0✓ yes
\ No newline at end of file From c8a587f394a5eb0edd0d4679dcae28c7dc58b002 Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Fri, 10 Jul 2026 13:37:34 +0200 Subject: [PATCH 06/13] Expand serialization benchmark: formats, corpus, report, samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Formats: add optimized compas_pb (protobuf) plus compas_pb_zip/zstd, and compas_msgpack (+ _zstd) — MessagePack over the JSON-shape tree (the Kumiki approach) applied to COMPAS types via an msgspec enc_hook on __jsondump__. All optional; skipped if the dep is missing. Corpus: add `graph` and collections of primitives/shapes (points, vectors, lines, frames, planes, boxes, spheres, circles). The harness now measures a list of Data or a single object transparently; metrics gains max/RMS coordinate error for lossy profiles. Report: executive summary is rendered client-side with a three-pill Uncompressed/Compressed/All filter that hides non-matching formats, re-normalizes the bars, and re-bases the summary; tiles report median ratios + range across subjects + win-counts. Samples: results/samples/ holds tiny encoded artifacts per subject — .json, .pb + .pb.json (protobuf bytes rendered back to JSON), .msgpack + .msgpack.json — to inspect each wire shape. Fairness: serialize a fresh fixture per format. Dumping to JSON accesses .guid (forcing it); a shared object let compas_pb re-serialize those forced guids, overstating its size on primitive/shape lists by ~30%. Co-Authored-By: Claude Opus 4.8 --- benchmarks/README.md | 102 +++++-- benchmarks/serialization/fixtures.py | 100 ++++++- benchmarks/serialization/formats.py | 110 +++++++ benchmarks/serialization/metrics.py | 21 +- benchmarks/serialization/report.py | 276 +++++++++--------- .../serialization/results/baseline_quick.csv | 192 ++++++++++-- .../serialization/results/baseline_quick.html | 97 +++++- .../serialization/results/samples/README.md | 19 ++ .../serialization/results/samples/boxes.json | 54 ++++ .../results/samples/boxes.msgpack | Bin 0 -> 461 bytes .../results/samples/boxes.msgpack.json | 54 ++++ .../serialization/results/samples/boxes.pb | Bin 0 -> 275 bytes .../results/samples/boxes.pb.json | 51 ++++ .../serialization/results/samples/graph.json | 50 ++++ .../results/samples/graph.msgpack | Bin 0 -> 382 bytes .../results/samples/graph.msgpack.json | 50 ++++ .../serialization/results/samples/graph.pb | Bin 0 -> 255 bytes .../results/samples/graph.pb.json | 74 +++++ .../serialization/results/samples/mesh.json | 55 ++++ .../results/samples/mesh.msgpack | Bin 0 -> 496 bytes .../results/samples/mesh.msgpack.json | 55 ++++ .../serialization/results/samples/mesh.pb | Bin 0 -> 261 bytes .../results/samples/mesh.pb.json | 53 ++++ .../results/samples/pointcloud.json | 28 ++ .../results/samples/pointcloud.msgpack | Bin 0 -> 203 bytes .../results/samples/pointcloud.msgpack.json | 28 ++ .../results/samples/pointcloud.pb | Bin 0 -> 164 bytes .../results/samples/pointcloud.pb.json | 22 ++ benchmarks/serialization/run.py | 28 +- benchmarks/serialization/samples.py | 127 ++++++++ 30 files changed, 1457 insertions(+), 189 deletions(-) create mode 100644 benchmarks/serialization/results/samples/README.md create mode 100644 benchmarks/serialization/results/samples/boxes.json create mode 100644 benchmarks/serialization/results/samples/boxes.msgpack create mode 100644 benchmarks/serialization/results/samples/boxes.msgpack.json create mode 100644 benchmarks/serialization/results/samples/boxes.pb create mode 100644 benchmarks/serialization/results/samples/boxes.pb.json create mode 100644 benchmarks/serialization/results/samples/graph.json create mode 100644 benchmarks/serialization/results/samples/graph.msgpack create mode 100644 benchmarks/serialization/results/samples/graph.msgpack.json create mode 100644 benchmarks/serialization/results/samples/graph.pb create mode 100644 benchmarks/serialization/results/samples/graph.pb.json create mode 100644 benchmarks/serialization/results/samples/mesh.json create mode 100644 benchmarks/serialization/results/samples/mesh.msgpack create mode 100644 benchmarks/serialization/results/samples/mesh.msgpack.json create mode 100644 benchmarks/serialization/results/samples/mesh.pb create mode 100644 benchmarks/serialization/results/samples/mesh.pb.json create mode 100644 benchmarks/serialization/results/samples/pointcloud.json create mode 100644 benchmarks/serialization/results/samples/pointcloud.msgpack create mode 100644 benchmarks/serialization/results/samples/pointcloud.msgpack.json create mode 100644 benchmarks/serialization/results/samples/pointcloud.pb create mode 100644 benchmarks/serialization/results/samples/pointcloud.pb.json create mode 100644 benchmarks/serialization/samples.py diff --git a/benchmarks/README.md b/benchmarks/README.md index 795ae5249bf1..17718cd36b76 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -22,12 +22,16 @@ For each **subject × size × format**: | `mesh` | jittered grid, float64 verts + int faces | none | | `mesh_attrs` | same + a per-vertex float | per-element (hybrid-layout cost) | | `pointcloud` | N float64 points | none¹ | +| `graph` | jittered grid, nodes (x,y,z) + edges | per-node coords | +| `points`, `vectors`, `lines`, `frames`, `planes`, `boxes`, `spheres`, `circles` | a list of N primitives/shapes | — | ¹ The COMPAS `Pointcloud` type has no per-point attribute slot, so the "with per-element attributes" case lives on `mesh_attrs`. -Fixtures are seeded ([`fixtures.py`](serialization/fixtures.py)) so runs are comparable and -reused across every format. +The primitive/shape subjects are **collections** (a Python `list` of N objects, a common +real-world payload — e.g. a list of frames as robot targets). Fixtures are seeded +([`fixtures.py`](serialization/fixtures.py)) so runs are comparable and reused across every +format; the harness measures a list or a single `Data` object transparently. ## Formats under test @@ -37,8 +41,16 @@ Registered in [`formats.py`](serialization/formats.py): - `json_zip` — zip-compressed JSON (size baseline); - `compas_pb` — protobuf binary via the `compas_pb` plugin (optional dep). We track the **optimized branch** (`benchmark/double-precision`): double precision, flat packed - coordinate arrays, and inline attribute maps. Skipped automatically if not installed. + coordinate arrays, columnar vertex attributes. Skipped automatically if not installed. The harness still quantifies any residual error (`max_abs_error` / `rms_error`). +- `compas_pb_zip` — the above, zip-compressed (DEFLATE); +- `compas_pb_zstd` — the above, zstandard-compressed (optional `zstandard` dep; similar + ratio to zip at ~3× faster compression). +- `compas_msgpack` — **MessagePack over the JSON-shape tree**, the approach from the Kumiki + project (which uses `msgspec`), applied to COMPAS types via an `msgspec` `enc_hook` on + `__jsondump__` (no `Mesh` subclass needed). Optional `msgspec` dep. Binary but + row-oriented / schemaless — a midpoint between JSON and the columnar `compas_pb`. +- `compas_msgpack_zstd` — the above, zstandard-compressed. An Arrow/columnar prototype registers the same way; the runner picks up any registered, available format automatically and skips those whose optional dependency is missing @@ -49,10 +61,18 @@ available format automatically and skips those whose optional dependency is miss Every run writes a CSV **and** a self-contained, theme-aware HTML report next to it (`results/.html`) — open it in a browser for a readable, per-subject view with grouped bars (round-trip time, wire size) and a full table. The CSV is the machine -record; the HTML is the human one. +record; the HTML is the human one. Each format serializes a **fresh** fixture, so one +format's dump (JSON accesses `.guid`) can't mutate what a later format encodes. + +It also writes **encoded-format samples** to `results/samples/` — tiny, fully-inspectable +fixtures encoded with the three main formats, so you can see the *shape* of each encoding: +`.json`, `.pb` + `.pb.json` (the protobuf bytes rendered back to +JSON, showing the flat/columnar wire structure), and `.msgpack` + +`.msgpack.json` (the row-oriented tree). Regenerate standalone with +`python -m benchmarks.serialization.samples`; skip during a run with `--no-samples`. ```bash -# Quick baseline (small sizes, fast) — writes results/baseline_quick.{csv,html} +# Quick baseline (small sizes, fast) — writes results/baseline_quick.{csv,html} + samples/ python -m benchmarks.serialization.run # Full PRD corpus (large; slow, memory-hungry) @@ -78,12 +98,13 @@ attribute maps, `compas_pb` goes from *larger and slower than JSON* (as shipped) |---|---|---|---|---| | mesh @10k, wire | 864 KB | 238 KB | 320 KB | **158 KB** | | mesh @10k, round-trip | 66 ms | 87 ms | **50 ms** | 58 ms | -| mesh_attrs @10k, wire | 1.1 MB | 339 KB | 651 KB | **273 KB** | +| mesh_attrs @10k, wire | 1.1 MB | 339 KB | 398 KB | **233 KB** | +| mesh_attrs @10k, round-trip | 67 ms | 97 ms | **52 ms** | 65 ms | | pointcloud @100k, wire | 5.5 MB | 2.7 MB | 2.3 MB | **2.2 MB** | | pointcloud @100k, round-trip | 343 ms | 551 ms | **186 ms** | 254 ms | -All four formats are now **lossless on every subject**. `compas_pb_zip` is smallest; -raw `compas_pb` is fastest (no compress step). Applied optimizations: +On the bulk-numeric types every format is **lossless** and `compas_pb` is smallest+fastest +(`_zip`/`_zstd` smallest on the wire, raw `compas_pb` fastest to load). Applied optimizations: - **Precision fixed** (`float → double`): coordinate error is **0** everywhere. - **Flat coordinate arrays** replaced a `PointData` message *per vertex/point* (each of @@ -98,8 +119,50 @@ raw `compas_pb` is fastest (no compress step). Applied optimizations: `face_sizes` length array, instead of one `FaceList` message per face. - **No `Any` wrapper on plain dicts/lists** — `AnyData` gained explicit `dict_value` / `list_value` arms, so every nested dict/list no longer carries a ~44-byte - `google.protobuf.Any` `type_url`. This cut `mesh_attrs@10k` from **1.1 MB → 651 KB** - (now below JSON) and helps Graph, fallback, and any nested container. + `google.protobuf.Any` `type_url`. Helps Graph, fallback, and any nested container. +- **Columnar attributes (mesh vertices + graph nodes/edges)** — each attribute name is + stored once with a packed value array (typed `double`/`int`/`bool`, generic fallback, + dense columns skip indices), instead of a dict per element. `mesh_attrs@10k`: + **1.1 MB → 398 KB** / **130 ms → 56 ms**; `graph@10k`: **931 KB → 360 KB** / **379 ms → + 87 ms** — both now smaller *and* faster to load than JSON. +- **guid/name only when explicitly set** — auto-generated guids and default names are no + longer written (an object serializes its guid only if `_guid` was set). This removes + ~40 bytes per object, including every `Point`/`Vector` nested in Lines/Frames/shapes. + `boxes@10k` **3.4 MB → 1.6 MB** (now < JSON 2.7 MB). Contract change: auto guids no longer + round-trip (they are session-local uuid4s); explicit guids still do. + +### What the expanded corpus shows + +The corpus also covers `graph` and collections of primitives/shapes, plus a third format: +`compas_msgpack` (MessagePack over the JSON-shape tree — the Kumiki approach). Findings: + +- **`compas_pb` is the smallest on 11/12 subjects** (bulk-numeric *and* primitive/shape + lists) after the guid fairness fix (see below). It is also **fastest to load on the + bulk-numeric types** (mesh, mesh_attrs, pointcloud, graph). For **small-primitive lists** + (points/vectors/lines/…) it is still smallest but *loads* slightly slower than JSON — + each element goes through registry dispatch + message unpack. See Pending #1. +- **`compas_msgpack` sits between JSON and `compas_pb`**: binary and ~30–45% smaller than + JSON with *very fast encode*, but row-oriented — so its **load speed is JSON-like** (no + columnar/bulk win). A cheap JSON upgrade that does not fix deserialization. +- **`frames`/`planes` show `lossless=no` for every format including JSON** (~1e-16 error): + `Frame`/`Plane` re-normalize their vectors on construction, so `normalize(normalize(v))` + differs at the last ULP. A COMPAS geometry quirk the fidelity check surfaces, not a + serialization defect. + +> **Fairness fix.** Each format serializes a *fresh* fixture. Serializing to JSON accesses +> `.guid` (forcing it onto the object); when all formats shared one object, `compas_pb` then +> re-serialized those forced guids, overstating its size on primitive/shape lists by ~30%. +> With independent objects, `compas_pb`'s smallest-on-11/12 result stands. + +The HTML report opens with a **three-pill toggle** (Uncompressed / Compressed / All) that +hides non-matching formats, re-normalizes the bars, and re-bases the summary — so you can +read *json vs compas_pb vs compas_msgpack* raw, or the compressed variants, in isolation. +The summary tiles report **median** ratios with their range across subjects (not a single +best), plus how many subjects `compas_pb` wins on size/speed. + +To inspect the actual encodings, see `results/samples/` (per subject: `.json`, `.pb` + +`.pb.json`, `.msgpack` + `.msgpack.json`) — `*.pb.json` shows the columnar/flat wire shape, +`*.msgpack.json` the row-oriented tree. The optimizations live on the `benchmark/double-precision` branch of the external `compas_pb` repo (regenerate `_pb2` with the pinned protoc `invocations.PROTOC_VERSION`, @@ -107,16 +170,15 @@ then `pip install -e .` into this `.venv`). ## Pending optimizations -1. **Columnar vertex attributes** — `mesh_attrs` is now small but still slower than JSON to - *load* (each vertex rebuilds a `DictData` and repeats the attribute-name string). Storing - attributes column-wise (name once + a packed value array aligned to vertices) is the - Phase-3 columnar layout; it should make attribute-heavy meshes beat JSON on both axes. -2. **Standalone `PointData` guid/name** — still serialized on every standalone Point/Line/ - Frame. Omitting them (design decision: binary parity with JSON vs compactness) would - shrink primitive-heavy payloads. -3. **Graph flat coordinates** — Graph nodes still carry coordinates inside per-node - `AnyData` dicts. A flat node-key + coordinate layout is the analog of the Mesh rewrite, - but node keys are arbitrary so it needs a small schema redesign. +1. **Batched primitive lists** — collections of small primitives load slightly slower than + JSON because each element goes through registry lookup + message unpack. A batched/columnar + encoding for homogeneous primitive lists (e.g. N points/frames as flat arrays) would close + it, the same way the mesh/graph rewrites did. +2. **Mesh face/edge attributes** — still stored as `map` (cheap when empty, + which is the common case). Could reuse the columnar layout when populated; low priority + since the corpus doesn't exercise face/edge attributes. +3. **Compare against MsgSpec** — evaluate the Kumiki-project MsgSpec-based serialization as an + additional format (next step). ## Status diff --git a/benchmarks/serialization/fixtures.py b/benchmarks/serialization/fixtures.py index b4b08f624fe5..6dbf63939b6a 100644 --- a/benchmarks/serialization/fixtures.py +++ b/benchmarks/serialization/fixtures.py @@ -17,8 +17,17 @@ import math import random +from compas.datastructures import Graph from compas.datastructures import Mesh +from compas.geometry import Box +from compas.geometry import Circle +from compas.geometry import Frame +from compas.geometry import Line +from compas.geometry import Plane +from compas.geometry import Point from compas.geometry import Pointcloud +from compas.geometry import Sphere +from compas.geometry import Vector DEFAULT_SEED = 42 @@ -82,10 +91,97 @@ def make_pointcloud(n_points, seed=DEFAULT_SEED): return Pointcloud(points) -# Subject catalogue: (label, factory taking a size -> Data object). -# Sizes follow PRD 10.1 but are selected by the runner (see run.py --sizes / --quick). +def make_graph(n_nodes, seed=DEFAULT_SEED): + """Build a deterministic jittered-grid graph with approximately ``n_nodes`` nodes. + + Nodes carry ``x``, ``y``, ``z`` coordinates; edges connect grid neighbours. + + Parameters + ---------- + n_nodes : int + Target number of nodes (nearest square of a ``side x side`` grid). + seed : int, optional + + Returns + ------- + :class:`compas.datastructures.Graph` + """ + rng = random.Random(seed) + side = max(2, int(round(math.sqrt(n_nodes)))) + graph = Graph() + keys = {} + for y in range(side): + for x in range(side): + keys[(x, y)] = graph.add_node(x=float(x), y=float(y), z=rng.uniform(-0.5, 0.5)) + for y in range(side): + for x in range(side): + if x < side - 1: + graph.add_edge(keys[(x, y)], keys[(x + 1, y)]) + if y < side - 1: + graph.add_edge(keys[(x, y)], keys[(x, y + 1)]) + return graph + + +def _make_primitive(kind, rng): + def coord(): + return [rng.uniform(-100.0, 100.0) for _ in range(3)] + + if kind == "point": + return Point(*coord()) + if kind == "vector": + return Vector(*coord()) + if kind == "line": + return Line(coord(), coord()) + if kind == "frame": + # near-orthonormal axes with jitter so the frame is well-conditioned + j = rng.uniform(-0.1, 0.1) + return Frame(coord(), [1.0, j, j], [j, 1.0, j]) + if kind == "plane": + return Plane(coord(), coord()) + if kind == "box": + f = Frame(coord(), [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]) + return Box(rng.uniform(1.0, 10.0), rng.uniform(1.0, 10.0), rng.uniform(1.0, 10.0), frame=f) + if kind == "sphere": + return Sphere(rng.uniform(1.0, 10.0), point=Point(*coord())) + if kind == "circle": + f = Frame(coord(), [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]) + return Circle(rng.uniform(1.0, 10.0), frame=f) + raise ValueError("Unknown primitive kind: {}".format(kind)) + + +def make_primitives(kind, count, seed=DEFAULT_SEED): + """Build a deterministic list of ``count`` primitives of the given ``kind``. + + Collections of primitives (e.g. a list of frames as robot targets) are a common + real-world payload; the harness measures the list as a whole. + + Parameters + ---------- + kind : str + One of point, vector, line, frame, plane, box, sphere, circle. + count : int + seed : int, optional + + Returns + ------- + list[:class:`compas.data.Data`] + """ + rng = random.Random(seed) + return [_make_primitive(kind, rng) for _ in range(count)] + + +_PRIMITIVE_KINDS = ["point", "vector", "line", "frame", "plane", "box", "sphere", "circle"] + + +# Subject catalogue: label -> factory(size, seed) returning a Data object (or list of them). +# Sizes are selected by the runner (see run.py PRESETS / DEFAULT_SIZES). SUBJECTS = { "mesh": lambda size, seed=DEFAULT_SEED: make_mesh(size, with_attributes=False, seed=seed), "mesh_attrs": lambda size, seed=DEFAULT_SEED: make_mesh(size, with_attributes=True, seed=seed), "pointcloud": lambda size, seed=DEFAULT_SEED: make_pointcloud(size, seed=seed), + "graph": lambda size, seed=DEFAULT_SEED: make_graph(size, seed=seed), } +# One subject per primitive kind (pluralized label), each a list of `size` primitives. +for _kind in _PRIMITIVE_KINDS: + _label = _kind + ("es" if _kind.endswith("x") else "s") + SUBJECTS[_label] = (lambda k: lambda size, seed=DEFAULT_SEED: make_primitives(k, size, seed=seed))(_kind) diff --git a/benchmarks/serialization/formats.py b/benchmarks/serialization/formats.py index 05e44035e39e..cb73f648adfb 100644 --- a/benchmarks/serialization/formats.py +++ b/benchmarks/serialization/formats.py @@ -133,3 +133,113 @@ def _pb_zip_loads(blob): note="protobuf binary, zip-compressed", ) ) + +try: + import zstandard # noqa: F401 + + _ZSTD_AVAILABLE = _PB_AVAILABLE +except ImportError: + _ZSTD_AVAILABLE = False + + +def _pb_zstd_dumps(obj): + import zstandard + + return zstandard.ZstdCompressor(level=10).compress(_pb_dumps(obj)) + + +def _pb_zstd_loads(blob): + import zstandard + + return _pb_loads(zstandard.ZstdDecompressor().decompress(blob)) + + +register( + Format( + "compas_pb_zstd", + _pb_zstd_dumps, + _pb_zstd_loads, + available=_ZSTD_AVAILABLE, + note="protobuf binary, zstandard-compressed", + ) +) + + +# --------------------------------------------------------------------------- +# MessagePack over the JSON-shape tree (the Kumiki-project approach, applied to COMPAS +# types via an msgspec enc_hook instead of Kumiki's own Serializable dataclasses). +# Binary but row-oriented / schemaless — a midpoint between JSON and the columnar compas_pb. +# --------------------------------------------------------------------------- + +try: + import msgspec # noqa: F401 + + _MSGPACK_AVAILABLE = True +except ImportError: + _MSGPACK_AVAILABLE = False + + +def _msgpack_enc_hook(obj): + # msgspec calls this for types it doesn't natively encode; COMPAS Data objects expose + # their {dtype, data, guid, name} dict via __jsondump__, and nested Data recurse the same way. + if hasattr(obj, "__jsondump__"): + return obj.__jsondump__() + raise NotImplementedError("Cannot msgpack-encode {}".format(type(obj))) + + +def _msgpack_reconstruct(node): + from compas.data.encoders import cls_from_dtype + + if isinstance(node, dict): + if "dtype" in node: + data = _msgpack_reconstruct(node["data"]) + cls = cls_from_dtype(node["dtype"], node.get("inheritance")) + return cls.__jsonload__(data, guid=node.get("guid"), name=node.get("name")) + return {key: _msgpack_reconstruct(value) for key, value in node.items()} + if isinstance(node, list): + return [_msgpack_reconstruct(item) for item in node] + return node + + +def _msgpack_dumps(obj): + import msgspec + + return msgspec.msgpack.encode(obj, enc_hook=_msgpack_enc_hook) + + +def _msgpack_loads(blob): + import msgspec + + return _msgpack_reconstruct(msgspec.msgpack.decode(blob)) + + +def _msgpack_zstd_dumps(obj): + import zstandard + + return zstandard.ZstdCompressor(level=10).compress(_msgpack_dumps(obj)) + + +def _msgpack_zstd_loads(blob): + import zstandard + + return _msgpack_loads(zstandard.ZstdDecompressor().decompress(blob)) + + +register( + Format( + "compas_msgpack", + _msgpack_dumps, + _msgpack_loads, + available=_MSGPACK_AVAILABLE, + note="msgpack over the JSON-shape tree (Kumiki-style)", + ) +) +register( + Format( + "compas_msgpack_zstd", + _msgpack_zstd_dumps, + _msgpack_zstd_loads, + available=_MSGPACK_AVAILABLE and _ZSTD_AVAILABLE, + note="msgpack, zstandard-compressed", + ) +) diff --git a/benchmarks/serialization/metrics.py b/benchmarks/serialization/metrics.py index 894ec3795e73..fc80f18be667 100644 --- a/benchmarks/serialization/metrics.py +++ b/benchmarks/serialization/metrics.py @@ -69,6 +69,20 @@ def numeric_error(original, roundtrip): return {"max_abs_error": max(diffs), "rms_error": rms} +def _data_of(obj): + """__data__ of a single Data object, or a list of __data__ for a collection subject.""" + if isinstance(obj, (list, tuple)): + return [item.__data__ for item in obj] + return obj.__data__ + + +def _hash_of(obj): + """Canonical hash of a single Data object, or of each item for a collection subject.""" + if isinstance(obj, (list, tuple)): + return [item.canonical_hash() for item in obj] + return obj.canonical_hash() + + def measure(fmt, obj, repeat=5): """Serialize/deserialize ``obj`` with ``fmt`` and return a metrics dict. @@ -93,9 +107,10 @@ def measure(fmt, obj, repeat=5): _, peak_bytes = tracemalloc.get_traced_memory() tracemalloc.stop() - data_equal = obj.__data__ == roundtrip.__data__ - hash_equal = obj.canonical_hash() == roundtrip.canonical_hash() - error = numeric_error(obj.__data__, roundtrip.__data__) + orig_data, rt_data = _data_of(obj), _data_of(roundtrip) + data_equal = orig_data == rt_data + hash_equal = _hash_of(obj) == _hash_of(roundtrip) + error = numeric_error(orig_data, rt_data) row = { "format": fmt.name, diff --git a/benchmarks/serialization/report.py b/benchmarks/serialization/report.py index 39850baeb47d..610c28ed683e 100644 --- a/benchmarks/serialization/report.py +++ b/benchmarks/serialization/report.py @@ -11,6 +11,7 @@ import datetime import html +import json # Validated categorical palette (dataviz skill reference instance): (light, dark) per slot. _SERIES = [ @@ -29,6 +30,94 @@ ("size_bytes", "Wire size", "bytes"), ] +# Client-side filter + summary re-render. __SLOTS__ is replaced with a {format: seriesSlot} map. +_FILTER_JS = """ +var SLOT = __SLOTS__; +var ROWS = JSON.parse(document.getElementById('rows-data').textContent); +function isCompressed(f){ return f.indexOf('zip') >= 0 || f.indexOf('zstd') >= 0; } +function inGroup(f, g){ return g === 'all' || (g === 'compressed') === isCompressed(f); } +function isPb(f){ return f.indexOf('compas_pb') === 0; } +function fmtInt(n){ return (+n).toLocaleString('en-US'); } +function fmtBytes(n){ var u=['B','KB','MB','GB'],i=0; n=+n; while(n>=1024&&i<3){n/=1024;i++;} return n.toFixed(1)+' '+u[i]; } +function fmtTime(s){ s=+s; return s<1 ? (s*1000).toFixed(1)+' ms' : s.toFixed(3)+' s'; } +function ratio(x){ return x.toFixed(1)+'\\u00d7'; } +function dot(f){ return ''; } +function median(a){ if(!a.length) return 0; var s=a.slice().sort(function(x,y){return x-y;}); var m=Math.floor(s.length/2); return s.length%2 ? s[m] : (s[m-1]+s[m])/2; } +function range(a){ return 'range '+Math.min.apply(null,a).toFixed(1)+'\\u2013'+Math.max.apply(null,a).toFixed(1)+'\\u00d7 across '+a.length+' subjects'; } +function currentGroup(){ var b=document.querySelector('.segmented button.active'); return b ? b.getAttribute('data-value') : 'all'; } +function minBy(a, f){ return a.reduce(function(x,y){return f(y)
'+big+'
'+lbl+'
'+sub+'
'; } +function factor(r, better, worse){ return r>=1 ? ratio(r)+' '+better : ratio(1/r)+' '+worse; } + +function renderSummary(rows){ + var subjects=[]; rows.forEach(function(r){ if(subjects.indexOf(r.subject)<0) subjects.push(r.subject); }); + var baseName = rows.some(function(r){return r.format==='json';}) ? 'json' + : (rows.some(function(r){return r.format==='json_zip';}) ? 'json_zip' : null); + var baseLabel = baseName || 'baseline'; + var per = subjects.map(function(subj){ + var sr = rows.filter(function(r){return r.subject===subj;}); + var maxSize = Math.max.apply(null, sr.map(function(r){return r.size;})); + return { subj: subj, size: maxSize, group: sr.filter(function(r){return r.size===maxSize;}) }; + }); + var sizeRatios=[], speedRatios=[], smallWins=0, fastWins=0, winTot=0; + per.forEach(function(p){ + var base = p.group.filter(function(r){return r.format===baseName;})[0]; + var pbs = p.group.filter(function(r){return isPb(r.format);}); + if(base && pbs.length){ + sizeRatios.push(base.size_bytes / minBy(pbs, function(r){return r.size_bytes;}).size_bytes); + speedRatios.push(base.roundtrip / minBy(pbs, function(r){return r.roundtrip;}).roundtrip); + winTot++; + if(isPb(minBy(p.group, function(r){return r.size_bytes;}).format)) smallWins++; + if(isPb(minBy(p.group, function(r){return r.roundtrip;}).format)) fastWins++; + } + }); + var tiles=''; + if(sizeRatios.length){ var ms=median(sizeRatios); tiles+=tile(factor(ms,'smaller','larger'), ms>=1?' win':'', 'median wire size vs '+baseLabel, range(sizeRatios)); } + if(speedRatios.length){ var mt=median(speedRatios); tiles+=tile(factor(mt,'faster','slower'), mt>=1?' win':'', 'median round-trip vs '+baseLabel, range(speedRatios)); } + if(winTot) tiles+=tile(smallWins+'/'+winTot, (smallWins===winTot?' win':''), 'subjects where compas_pb is smallest', 'and fastest to load on '+fastWins+'/'+winTot); + var head='subjectelementssmallestvs '+baseLabel + +'fastest round-tripvs '+baseLabel+'lossless'; + var body=''; + per.forEach(function(p){ + if(!p.group.length) return; + var base = p.group.filter(function(r){return r.format===baseName;})[0]; + var smallest = minBy(p.group, function(r){return r.size_bytes;}); + var fastest = minBy(p.group, function(r){return r.roundtrip;}); + var sr = base ? (base.size_bytes/smallest.size_bytes).toFixed(2)+'\\u00d7' : '\\u2014'; + var spr = base ? (base.roundtrip/fastest.roundtrip).toFixed(2)+'\\u00d7' : '\\u2014'; + var pb = p.group.filter(function(r){return isPb(r.format);})[0]; + var badge = pb ? (pb.lossless ? '\\u2713 yes' : '\\u2717 no') : '\\u2014'; + body+=''+p.subj+''+fmtInt(p.size)+'' + +''+dot(smallest.format)+smallest.format+' \\u00b7 '+fmtBytes(smallest.size_bytes)+''+sr+'' + +''+dot(fastest.format)+fastest.format+' \\u00b7 '+fmtTime(fastest.roundtrip)+''+spr+'' + +''+badge+''; + }); + return '

Summary

'+tiles+'
'+head+body+'
'; +} + +function applyFilter(){ + var g = currentGroup(); + document.querySelectorAll('[data-format]').forEach(function(el){ + el.style.display = inGroup(el.getAttribute('data-format'), g) ? '' : 'none'; + }); + document.querySelectorAll('.sizegroup').forEach(function(sg){ + var fills = [].slice.call(sg.querySelectorAll('.bar-row')).filter(function(r){return r.style.display!=='none';}) + .map(function(r){return r.querySelector('.fill');}); + var max = Math.max.apply(null, fills.map(function(f){return parseFloat(f.dataset.value);}).concat([0])); + fills.forEach(function(f){ f.style.width = max>0 ? (parseFloat(f.dataset.value)/max*100).toFixed(1)+'%' : '0%'; }); + }); + document.getElementById('summary-body').innerHTML = renderSummary(ROWS.filter(function(r){return inGroup(r.format, g);})); +} +document.querySelectorAll('.segmented button').forEach(function(b){ + b.addEventListener('click', function(){ + document.querySelectorAll('.segmented button').forEach(function(x){ x.classList.remove('active'); }); + b.classList.add('active'); + applyFilter(); + }); +}); +applyFilter(); +""" + def _fmt_int(n): return "{:,}".format(int(n)) @@ -138,6 +227,16 @@ def _css(colors): .tile .sub { font-size: 11px; color: var(--muted); margin-top: 1px; } .win { color: var(--good); font-weight: 600; } h2.section { margin-top: 8px; } +.controls { margin: 14px 0 4px; display: flex; align-items: center; gap: 12px; } +.controls-label { font-size: 13px; color: var(--text-secondary); } +.segmented { display: inline-flex; background: var(--track); border: 1px solid var(--border); + border-radius: 9px; padding: 2px; gap: 2px; } +.segmented button { font: inherit; font-size: 13px; color: var(--text-secondary); cursor: pointer; + background: transparent; border: 0; border-radius: 7px; padding: 5px 14px; line-height: 1.4; } +.segmented button:hover { color: var(--text-primary); } +.segmented button.active { background: var(--surface); color: var(--text-primary); font-weight: 600; + box-shadow: 0 1px 2px rgba(0,0,0,0.10); } +.tile .rng { font-size: 11px; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; } """.replace("%SERIES_LIGHT%", series_light).replace("%SERIES_DARK%", series_dark) @@ -155,8 +254,10 @@ def _legend(rows, colors): seen.append(r["format"]) slot = _slot(colors, r["format"]) parts.append( - '' - "{} · {}".format(slot, html.escape(r["format"]), html.escape(r.get("note", ""))) + '' + "{fmt} · {note}".format( + slot=slot, fmt=html.escape(r["format"]), note=html.escape(r.get("note", "")) + ) ) parts.append("") return "".join(parts) @@ -178,14 +279,15 @@ def _bars(subject_rows, colors, metric_key, kind): width = float(r[metric_key]) / group_max * 100.0 slot = _slot(colors, r["format"]) rows_html.append( - '
' + '
' '
{name}
' - '
' + '
' '
{val}
' "
".format( name=html.escape(r["format"]), w=width, s=slot, + dv=float(r[metric_key]), val=_fmt_value(r[metric_key], kind), ) ) @@ -209,7 +311,7 @@ def _table(subject_rows, colors): lossless = str(r["lossless"]).lower() in ("true", "1") badge = '✓ yes' if lossless else '✗ no' body.append( - "" + '' "{size}" '{fmt}' "{wire}{ratio}×" @@ -233,130 +335,6 @@ def _table(subject_rows, colors): return '
{}{}
'.format(head, "".join(body)) -def _ratio(x): - return "{:.1f}×".format(x) - - -def _is_lossless(row): - return str(row["lossless"]).lower() in ("true", "1") - - -def _exec_summary(rows, colors, subjects): - """Headline stat tiles + a one-line takeaway + a per-subject winners table. - - Everything is derived from the largest measured size of each subject and expressed - against JSON, so a reader gets the conclusion before any of the detail below. - """ - baseline = "json" - binary = "compas_pb" - per = [] # (subject, size, group_map, smallest_row, fastest_row) - for subj in subjects: - srows = [r for r in rows if r["subject"] == subj] - max_size = max(int(r["size"]) for r in srows) - group = [r for r in srows if int(r["size"]) == max_size] - gmap = {r["format"]: r for r in group} - smallest = min(group, key=lambda r: float(r["size_bytes"])) - fastest = min(group, key=lambda r: float(r["roundtrip_median_s"])) - per.append((subj, max_size, gmap, smallest, fastest)) - - # Tiles: best size / round-trip gains of the binary format vs JSON, and lossless coverage. - size_gain = speed_gain = None - lossless_hits = lossless_total = 0 - for subj, size, gmap, _, _ in per: - if baseline in gmap and binary in gmap: - j, b = gmap[baseline], gmap[binary] - sr = float(j["size_bytes"]) / float(b["size_bytes"]) - spd = float(j["roundtrip_median_s"]) / float(b["roundtrip_median_s"]) - if size_gain is None or sr > size_gain[0]: - size_gain = (sr, subj, size) - if speed_gain is None or spd > speed_gain[0]: - speed_gain = (spd, subj, size) - lossless_total += 1 - lossless_hits += _is_lossless(b) - - tiles = [] - if size_gain: - tiles.append( - '
{r} smaller
' - '
{bin} vs JSON on the wire
' - '
best: {subj} @ {n} elements
'.format( - r=_ratio(size_gain[0]), bin=binary, subj=html.escape(size_gain[1]), n=_fmt_int(size_gain[2]) - ) - ) - if speed_gain: - tiles.append( - '
{r} faster
' - '
{bin} round-trip vs JSON
' - '
best: {subj} @ {n} elements
'.format( - r=_ratio(speed_gain[0]), bin=binary, subj=html.escape(speed_gain[1]), n=_fmt_int(speed_gain[2]) - ) - ) - if lossless_total: - ok = lossless_hits == lossless_total - tiles.append( - '
{h}/{t}
' - '
subjects lossless ({bin})
' - '
exact round-trip of __data__
'.format( - cls=" win" if ok else "", h=lossless_hits, t=lossless_total, bin=binary - ) - ) - - # Winners table: per subject at its largest size, the smallest and fastest format vs JSON. - head = ( - "subjectelementssmallestvs JSON" - "fastest round-tripvs JSON{bin} lossless".format(bin=binary) - ) - body = [] - for subj, size, gmap, smallest, fastest in per: - j = gmap.get(baseline) - size_ratio = "{:.2f}×".format(float(j["size_bytes"]) / float(smallest["size_bytes"])) if j else "—" - speed_ratio = "{:.2f}×".format(float(j["roundtrip_median_s"]) / float(fastest["roundtrip_median_s"])) if j else "—" - b = gmap.get(binary) - badge = ( - ('✓ yes' if _is_lossless(b) else '✗ no') - if b - else '' - ) - body.append( - "{subj}{n}" - '{sf} · {sb}{sr}' - '{ff} · {ft}{spr}' - "{badge}".format( - subj=html.escape(subj), - n=_fmt_int(size), - s1=_slot(colors, smallest["format"]), - sf=html.escape(smallest["format"]), - sb=_fmt_bytes(smallest["size_bytes"]), - sr=size_ratio, - s2=_slot(colors, fastest["format"]), - ff=html.escape(fastest["format"]), - ft=_fmt_time(fastest["roundtrip_median_s"]), - spr=speed_ratio, - badge=badge, - ) - ) - - takeaway = "" - if size_gain and speed_gain: - takeaway = ( - '

On the largest payloads, {bin} (protobuf: double + flat ' - "coordinate arrays) is the smallest and fastest option — up to {sr} smaller and " - "{spd} faster to load than compact JSON, {loss}.

".format( - bin=binary, - sr=_ratio(size_gain[0]), - spd=_ratio(speed_gain[0]), - loss=("losslessly" if lossless_hits == lossless_total else "with remaining fidelity notes below"), - ) - ) - - return ( - '

Summary

' - + takeaway - + '
{}
'.format("".join(tiles)) - + '
{}{}
'.format(head, "".join(body)) - ) - - def build_html(rows, meta=None): """Return a full standalone HTML document for the given result rows. @@ -384,7 +362,19 @@ def build_html(rows, meta=None): if key in meta: meta_bits.append("{} {}".format(key, meta[key])) - sections = [_exec_summary(rows, colors, subjects), _legend(rows, colors)] + controls = ( + '
Show formats' + '
' + '' + '' + '' + "
" + ) + sections = [ + controls, + '
', + _legend(rows, colors), + ] for subject in subjects: subject_rows = [r for r in rows if r["subject"] == subject] sections.append("

{}

".format(html.escape(subject))) @@ -393,6 +383,23 @@ def build_html(rows, meta=None): sections.append(_bars(subject_rows, colors, metric_key, kind)) sections.append(_table(subject_rows, colors)) + data_rows = [ + { + "subject": r["subject"], + "size": int(r["size"]), + "format": r["format"], + "size_bytes": int(r["size_bytes"]), + "roundtrip": float(r["roundtrip_median_s"]), + "lossless": str(r["lossless"]).lower() in ("true", "1"), + } + for r in rows + ] + slot_map = {r["format"]: _slot(colors, r["format"]) for r in rows} + script = ( + '' + "" + ).format(data=json.dumps(data_rows), js=_FILTER_JS.replace("__SLOTS__", json.dumps(slot_map))) + return ( "" "" @@ -400,9 +407,14 @@ def build_html(rows, meta=None): "
" "

COMPAS serialization benchmark

" "

{meta}

" - "{body}" + "{body}{script}" "
" - ).format(css=_css(colors), meta=html.escape(" · ".join(meta_bits)), body="".join(sections)) + ).format( + css=_css(colors), + meta=html.escape(" · ".join(meta_bits)), + body="".join(sections), + script=script, + ) def write_html(rows, out_path, meta=None): diff --git a/benchmarks/serialization/results/baseline_quick.csv b/benchmarks/serialization/results/baseline_quick.csv index cf9d8dc24e6a..7bdf036e0bb5 100644 --- a/benchmarks/serialization/results/baseline_quick.csv +++ b/benchmarks/serialization/results/baseline_quick.csv @@ -1,25 +1,169 @@ subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -mesh,1000,json,82154,1.0,0.001566,8.3e-05,0.003726,0.000121,0.005292,52.457,22.047,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,json_zip,28052,2.929,0.003475,9e-05,0.003789,0.001924,0.007265,8.071,7.403,1615280,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,1000,compas_pb,32957,2.493,0.00162,0.007135,0.00338,7.8e-05,0.005,20.344,9.75,870324,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh,1000,compas_pb_zip,16376,5.017,0.002084,5.1e-05,0.003331,3e-06,0.005415,7.856,4.917,904677,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh,10000,json,884888,1.0,0.016789,0.002451,0.045899,0.003391,0.062688,52.708,19.279,16027789,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,json_zip,243864,3.629,0.038994,0.002556,0.047277,0.003323,0.08627,6.254,5.158,16030454,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,10000,compas_pb,328068,2.697,0.015875,9.9e-05,0.033815,0.004066,0.04969,20.666,9.702,8632468,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh,10000,compas_pb_zip,162321,5.451,0.022556,0.000355,0.034286,0.003739,0.056843,7.196,4.734,8962740,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh_attrs,1000,json,112098,1.0,0.001881,7.1e-05,0.003836,0.002122,0.005718,59.583,29.221,1666239,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,json_zip,38109,2.942,0.00433,0.000105,0.003878,8.9e-05,0.008208,8.801,9.826,1669104,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,1000,compas_pb,66663,1.682,0.005835,0.000327,0.006685,0.00019,0.01252,11.426,9.972,1281853,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh_attrs,1000,compas_pb_zip,28365,3.952,0.006733,9.7e-05,0.006929,6.6e-05,0.013662,4.213,4.094,1347488,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh_attrs,10000,json,1177508,1.0,0.021072,0.002351,0.047697,0.003086,0.068769,55.881,24.687,16560353,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,json_zip,347074,3.393,0.051664,0.003469,0.047957,0.004089,0.099621,6.718,7.237,16567738,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,10000,compas_pb,666958,1.765,0.05772,0.001917,0.07199,0.005181,0.12971,11.555,9.265,12575853,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh_attrs,10000,compas_pb_zip,279834,4.208,0.069739,0.000465,0.073197,0.003803,0.142936,4.013,3.823,13245015,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -pointcloud,10000,json,580633,1.0,0.013699,0.000116,0.014419,0.002765,0.028118,42.385,40.269,4261534,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,json_zip,280725,2.068,0.033433,0.002402,0.014345,0.00249,0.047778,8.397,19.57,4269071,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,10000,compas_pb,240124,2.418,0.003262,3.9e-05,0.010587,0.002621,0.013849,73.603,22.682,3599513,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -pointcloud,10000,compas_pb_zip,228837,2.537,0.009202,7.7e-05,0.010907,0.002296,0.02011,24.868,20.98,3840761,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -pointcloud,100000,json,5804860,1.0,0.150237,0.004721,0.186795,0.017851,0.337033,38.638,31.076,42597425,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,json_zip,2792760,2.079,0.348003,0.009456,0.180972,0.028574,0.528974,8.025,15.432,42604858,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,100000,compas_pb,2400128,2.419,0.032329,0.00067,0.15471,0.00788,0.187039,74.241,15.514,35996537,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -pointcloud,100000,compas_pb_zip,2286081,2.539,0.093947,0.000508,0.164759,0.019508,0.258705,24.334,13.875,38392481,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,1000,json,285582,1.0,0.007785,0.001844,0.041193,0.00026,0.048978,36.686,6.933,1727364,True,True,True,0.0,0.0,"compact text, lossless" +boxes,1000,json_zip,89866,3.178,0.011599,0.001823,0.040598,0.000287,0.052197,7.748,2.214,1729869,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +boxes,1000,compas_pb,131015,2.18,0.006713,0.013195,0.045559,0.002559,0.052272,19.516,2.876,1339834,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +boxes,1000,compas_pb_zip,52308,5.46,0.008356,0.000762,0.046564,0.003048,0.05492,6.26,1.123,1472733,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,1000,compas_pb_zstd,50046,5.706,0.007656,0.000757,0.045315,0.000161,0.05297,6.537,1.104,1470882,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +boxes,1000,compas_msgpack,230003,1.242,0.003446,0.001534,0.046462,0.000112,0.049908,66.753,4.95,2664336,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +boxes,1000,compas_msgpack_zstd,79439,3.595,0.005562,0.00172,0.04691,0.000121,0.052472,14.284,1.693,2896372,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +boxes,10000,json,2855355,1.0,0.083882,0.015251,0.415532,0.011624,0.499414,34.04,6.872,17297673,True,True,True,0.0,0.0,"compact text, lossless" +boxes,10000,json_zip,892072,3.201,0.118557,0.015591,0.431748,0.012822,0.550306,7.524,2.066,17300178,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +boxes,10000,compas_pb,1310015,2.18,0.070668,0.000381,0.482124,0.009117,0.552792,18.538,2.717,13440482,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +boxes,10000,compas_pb_zip,520863,5.482,0.084411,0.000585,0.480021,0.012843,0.564432,6.171,1.085,14751629,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,10000,compas_pb_zstd,497195,5.743,0.079089,0.001297,0.4818,0.002833,0.560889,6.287,1.032,14750434,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +boxes,10000,compas_msgpack,2300003,1.241,0.035114,0.020122,0.513876,0.020949,0.54899,65.501,4.476,26841536,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +boxes,10000,compas_msgpack_zstd,795391,3.59,0.056956,0.014663,0.500645,0.023084,0.557601,13.965,1.589,29141572,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +circles,1000,json,237208,1.0,0.006579,0.002177,0.038615,0.003538,0.045193,36.056,6.143,1542873,True,True,True,0.0,0.0,"compact text, lossless" +circles,1000,json_zip,68274,3.474,0.0096,0.001692,0.039459,0.000599,0.049059,7.112,1.73,1545762,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +circles,1000,compas_pb,163015,1.455,0.007589,0.00181,0.046472,0.000128,0.054062,21.48,3.508,1358721,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +circles,1000,compas_pb_zip,63498,3.736,0.009726,0.001689,0.046838,0.000123,0.056564,6.529,1.356,1522964,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +circles,1000,compas_pb_zstd,61969,3.828,0.009248,0.00187,0.045993,0.003841,0.055241,6.701,1.347,1521769,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +circles,1000,compas_msgpack,204003,1.163,0.00364,0.001583,0.0478,0.004097,0.05144,56.047,4.268,2531491,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +circles,1000,compas_msgpack_zstd,62162,3.816,0.004772,0.001578,0.045873,0.003392,0.050644,13.027,1.355,2735527,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +circles,10000,json,2372279,1.0,0.066367,0.015783,0.431295,0.018532,0.497662,35.745,5.5,15454648,True,True,True,0.0,0.0,"compact text, lossless" +circles,10000,json_zip,677524,3.501,0.097308,0.016723,0.431064,0.009799,0.528372,6.963,1.572,15457145,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +circles,10000,compas_pb,1630015,1.455,0.078108,0.015657,0.490322,0.005567,0.56843,20.869,3.324,13630497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +circles,10000,compas_pb_zip,631606,3.756,0.101384,0.015583,0.501556,0.000958,0.602941,6.23,1.259,15261684,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +circles,10000,compas_pb_zstd,606407,3.912,0.091088,0.017456,0.502684,0.001467,0.593771,6.657,1.206,15260545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +circles,10000,compas_msgpack,2040003,1.163,0.032588,0.014647,0.499202,0.017768,0.53179,62.6,4.087,25510523,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +circles,10000,compas_msgpack_zstd,608922,3.896,0.048848,0.017091,0.496467,0.008915,0.545315,12.466,1.227,27551655,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +frames,1000,json,295873,1.0,0.007729,0.001793,0.021617,0.00165,0.029346,38.281,13.687,1384395,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"compact text, lossless" +frames,1000,json_zip,109726,2.696,0.014499,0.001534,0.021291,0.000281,0.03579,7.568,5.154,1386900,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"zip-compressed json, size baseline" +frames,1000,compas_pb,141015,2.098,0.005494,0.000189,0.032896,0.003048,0.03839,25.666,4.287,987572,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, double + flat arrays (optimized)" +frames,1000,compas_pb_zip,71467,4.14,0.008474,0.000545,0.026521,0.000141,0.034995,8.434,2.695,1129815,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zip-compressed" +frames,1000,compas_pb_zstd,69763,4.241,0.00686,6.6e-05,0.02596,0.00303,0.03282,10.17,2.687,1128620,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zstandard-compressed" +frames,1000,compas_msgpack,180003,1.644,0.002916,0.001409,0.025497,0.00045,0.028413,61.729,7.06,2083642,False,False,False,4.440892098500626e-16,6.299702658387308e-17,msgpack over the JSON-shape tree (Kumiki-style) +frames,1000,compas_msgpack_zstd,96688,3.06,0.004674,0.00152,0.02526,0.000197,0.029934,20.688,3.828,2261158,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"msgpack, zstandard-compressed" +frames,10000,json,2959373,1.0,0.07323,0.015906,0.22278,0.006959,0.296009,40.412,13.284,13880263,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"compact text, lossless" +frames,10000,json_zip,1090022,2.715,0.134516,0.014495,0.222859,0.008448,0.357376,8.103,4.891,13882928,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"zip-compressed json, size baseline" +frames,10000,compas_pb,1410015,2.099,0.055502,0.000407,0.273539,0.006856,0.329041,25.405,5.155,9920052,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, double + flat arrays (optimized)" +frames,10000,compas_pb_zip,712585,4.153,0.087012,0.001495,0.281689,0.006767,0.368701,8.189,2.53,11331295,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zip-compressed" +frames,10000,compas_pb_zstd,707041,4.186,0.073682,0.000967,0.274891,0.004163,0.348574,9.596,2.572,11330100,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zstandard-compressed" +frames,10000,compas_msgpack,1800003,1.644,0.029463,0.014611,0.291106,0.004979,0.320569,61.094,6.183,21017794,False,False,False,5.551115123125783e-16,6.326276205293956e-17,msgpack over the JSON-shape tree (Kumiki-style) +frames,10000,compas_msgpack_zstd,964081,3.07,0.057417,0.011557,0.283381,0.005289,0.340798,16.791,3.402,22817830,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"msgpack, zstandard-compressed" +graph,1000,json,76719,1.0,0.001761,7.1e-05,0.013687,0.00378,0.015448,43.567,5.605,1938217,True,True,True,0.0,0.0,"compact text, lossless" +graph,1000,json_zip,24330,3.153,0.003479,0.000217,0.012466,0.000252,0.015946,6.993,1.952,1940890,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +graph,1000,compas_pb,37178,2.064,0.004035,0.000133,0.004036,0.000107,0.008071,9.214,9.211,1115572,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +graph,1000,compas_pb_zip,15463,4.961,0.004744,9.3e-05,0.003976,8.9e-05,0.008721,3.259,3.889,1154142,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +graph,1000,compas_pb_zstd,16070,4.774,0.004421,0.000112,0.00402,0.000267,0.008442,3.635,3.997,1152783,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +graph,1000,compas_msgpack,53875,1.424,0.000605,3e-05,0.01465,0.000282,0.015255,89.056,3.677,2544153,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +graph,1000,compas_msgpack_zstd,17746,4.323,0.001218,4.8e-05,0.014688,0.002632,0.015905,14.571,1.208,2598061,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +graph,10000,json,793664,1.0,0.016957,0.000234,0.132289,0.004032,0.149246,46.803,5.999,19036162,True,True,True,0.0,0.0,"compact text, lossless" +graph,10000,json_zip,213388,3.719,0.033907,0.004364,0.137011,0.006698,0.170919,6.293,1.557,19020672,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +graph,10000,compas_pb,368817,2.152,0.039935,0.000462,0.037609,0.004822,0.077544,9.235,9.807,11049444,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +graph,10000,compas_pb_zip,142716,5.561,0.047998,0.001187,0.040069,0.008138,0.088067,2.973,3.562,11419657,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +graph,10000,compas_pb_zstd,185816,4.271,0.043525,0.001102,0.038052,0.004755,0.081577,4.269,4.883,11418294,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +graph,10000,compas_msgpack,564802,1.405,0.008534,0.003907,0.168116,0.005396,0.17665,66.182,3.36,25119679,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +graph,10000,compas_msgpack_zstd,118953,6.672,0.011117,0.003719,0.168573,0.007798,0.179691,10.7,0.706,25684514,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +lines,1000,json,218115,1.0,0.007568,0.001738,0.008024,6.6e-05,0.015591,28.822,27.184,1041873,True,True,True,0.0,0.0,"compact text, lossless" +lines,1000,json_zip,86999,2.507,0.011715,0.001649,0.008508,6.3e-05,0.020224,7.426,10.225,1044906,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +lines,1000,compas_pb,109015,2.001,0.006983,3.3e-05,0.011712,4.3e-05,0.018695,15.612,9.308,722835,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +lines,1000,compas_pb_zip,51798,4.211,0.008763,0.000162,0.012071,0.000186,0.020835,5.911,4.291,833078,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +lines,1000,compas_pb_zstd,50170,4.348,0.007936,9.8e-05,0.011901,0.000103,0.019837,6.322,4.216,831883,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +lines,1000,compas_msgpack,143003,1.525,0.004581,0.001546,0.011647,0.00011,0.016228,31.215,12.278,1663713,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +lines,1000,compas_msgpack_zstd,78551,2.777,0.006112,0.001465,0.011864,0.000568,0.017976,12.852,6.621,1806749,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +lines,10000,json,2181230,1.0,0.081256,0.016077,0.090389,0.00919,0.171645,26.844,24.132,10462004,True,True,True,0.0,0.0,"compact text, lossless" +lines,10000,json_zip,862928,2.528,0.118228,0.018745,0.096666,0.006666,0.214894,7.299,8.927,10464509,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +lines,10000,compas_pb,1090015,2.001,0.073789,0.002596,0.128516,0.005967,0.202305,14.772,8.482,7279619,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +lines,10000,compas_pb_zip,515699,4.23,0.087276,0.000933,0.130785,0.006029,0.218061,5.909,3.943,8370862,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +lines,10000,compas_pb_zstd,498282,4.378,0.078514,0.000494,0.129217,0.004041,0.207731,6.346,3.856,8369667,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +lines,10000,compas_msgpack,1430003,1.525,0.047991,0.015,0.132507,0.001501,0.180498,29.797,10.792,16848977,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +lines,10000,compas_msgpack_zstd,769341,2.835,0.067813,0.012512,0.141122,0.003686,0.208935,11.345,5.452,18277541,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh,1000,json,82154,1.0,0.001502,2.5e-05,0.0036,2.5e-05,0.005101,54.706,22.823,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,json_zip,28050,2.929,0.003545,0.000102,0.003756,6.9e-05,0.007301,7.913,7.469,1614336,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,1000,compas_pb,32913,2.496,0.001739,1.9e-05,0.00328,3.9e-05,0.005019,18.924,10.035,878003,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,1000,compas_pb_zip,16331,5.031,0.00232,1.6e-05,0.003393,3.7e-05,0.005713,7.038,4.813,912308,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,1000,compas_pb_zstd,16203,5.07,0.002085,3.3e-05,0.00332,3.8e-05,0.005405,7.77,4.881,910949,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh,1000,compas_msgpack,58668,1.4,0.00043,1.4e-05,0.007532,0.002525,0.007962,136.477,7.789,2063130,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh,1000,compas_msgpack_zstd,25135,3.269,0.001021,1.7e-05,0.007472,3.1e-05,0.008493,24.614,3.364,2121831,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh,10000,json,884888,1.0,0.016384,0.003158,0.044177,0.004078,0.060561,54.008,20.031,16027789,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,json_zip,243866,3.629,0.039129,0.000352,0.043856,0.003776,0.082985,6.232,5.561,16035062,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,10000,compas_pb,328024,2.698,0.017031,0.000139,0.034531,0.005207,0.051562,19.261,9.499,8718587,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,10000,compas_pb_zip,162262,5.453,0.023818,0.000115,0.034543,0.004322,0.05836,6.813,4.697,9047715,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,10000,compas_pb_zstd,172651,5.125,0.01989,0.000747,0.03334,0.003896,0.05323,8.68,5.179,9046644,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh,10000,compas_msgpack,621054,1.425,0.004903,0.000495,0.088312,0.002331,0.093215,126.672,7.033,20579024,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh,10000,compas_msgpack_zstd,203525,4.348,0.008411,0.000364,0.087099,0.001089,0.095511,24.196,2.337,21200111,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh_attrs,1000,json,112098,1.0,0.001986,6.7e-05,0.003914,2.4e-05,0.0059,56.457,28.639,1666431,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,json_zip,38109,2.942,0.004442,0.000115,0.003943,2.9e-05,0.008385,8.58,9.665,1669096,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,1000,compas_pb,41120,2.726,0.002045,0.000159,0.003583,0.003079,0.005629,20.104,11.475,967891,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,1000,compas_pb_zip,24312,4.611,0.0026,0.00012,0.003513,3e-06,0.006113,9.351,6.92,1010407,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,1000,compas_pb_zstd,24277,4.617,0.002336,2.6e-05,0.003387,5.1e-05,0.005723,10.392,7.169,1009044,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh_attrs,1000,compas_msgpack,76076,1.474,0.00044,1.8e-05,0.008014,0.003104,0.008454,172.704,9.493,2087922,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh_attrs,1000,compas_msgpack_zstd,33792,3.317,0.001301,3.3e-05,0.008099,2.8e-05,0.0094,25.98,4.172,2164031,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh_attrs,10000,json,1177508,1.0,0.019797,0.003064,0.048608,0.004987,0.068405,59.479,24.224,16560465,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,json_zip,347070,3.393,0.051306,0.002635,0.051502,0.001903,0.102808,6.765,6.739,16563738,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,10000,compas_pb,408041,2.886,0.019976,0.002875,0.035178,0.00382,0.055153,20.427,11.599,9597267,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,10000,compas_pb_zip,238533,4.936,0.028754,0.002849,0.041106,0.003493,0.06986,8.296,5.803,10007512,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,10000,compas_pb_zstd,238887,4.929,0.02227,0.000264,0.034494,0.004362,0.056764,10.727,6.925,10005341,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh_attrs,10000,compas_msgpack,791054,1.489,0.004515,0.000147,0.092655,0.002137,0.09717,175.222,8.538,20822216,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh_attrs,10000,compas_msgpack_zstd,282066,4.175,0.01016,0.000342,0.089878,0.007055,0.100039,27.761,3.138,21611119,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +planes,1000,json,225141,1.0,0.005406,0.001551,0.008302,0.002691,0.013708,41.646,27.118,1048924,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"compact text, lossless" +planes,1000,json_zip,87456,2.574,0.010019,0.001533,0.008831,5.8e-05,0.01885,8.729,9.903,1051621,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"zip-compressed json, size baseline" +planes,1000,compas_pb,110015,2.046,0.004704,8.5e-05,0.013028,0.002934,0.017733,23.387,8.444,722652,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, double + flat arrays (optimized)" +planes,1000,compas_pb_zip,52297,4.305,0.006098,0.000107,0.012638,8e-05,0.018735,8.577,4.138,833895,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zip-compressed" +planes,1000,compas_pb_zstd,50611,4.448,0.005746,0.000207,0.013177,0.000112,0.018923,8.808,3.841,832700,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zstandard-compressed" +planes,1000,compas_msgpack,147003,1.532,0.00254,0.001398,0.012447,0.00013,0.014986,57.881,11.811,1664479,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,msgpack over the JSON-shape tree (Kumiki-style) +planes,1000,compas_msgpack_zstd,79365,2.837,0.004019,0.001495,0.012334,0.00289,0.016353,19.749,6.435,1811515,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"msgpack, zstandard-compressed" +planes,10000,json,2251968,1.0,0.054689,0.014844,0.09411,0.00626,0.1488,41.177,23.929,10532543,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"compact text, lossless" +planes,10000,json_zip,866566,2.599,0.10046,0.015386,0.100463,0.005787,0.200923,8.626,8.626,10535528,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"zip-compressed json, size baseline" +planes,10000,compas_pb,1100015,2.047,0.045995,0.000161,0.130369,0.005152,0.176363,23.916,8.438,7279204,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, double + flat arrays (optimized)" +planes,10000,compas_pb_zip,520659,4.325,0.062105,0.000212,0.140755,0.005426,0.20286,8.383,3.699,8380447,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zip-compressed" +planes,10000,compas_pb_zstd,508937,4.425,0.056183,0.00043,0.134108,0.004695,0.190291,9.059,3.795,8379252,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zstandard-compressed" +planes,10000,compas_msgpack,1470003,1.532,0.024178,0.014464,0.133392,0.001057,0.15757,60.8,11.02,16858631,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,msgpack over the JSON-shape tree (Kumiki-style) +planes,10000,compas_msgpack_zstd,780156,2.887,0.039609,0.01471,0.141388,0.006416,0.180997,19.697,5.518,18327187,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"msgpack, zstandard-compressed" +pointcloud,10000,json,580633,1.0,0.013331,0.003144,0.013293,0.003293,0.026624,43.555,43.68,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,json_zip,280724,2.068,0.033267,9.5e-05,0.014547,0.002679,0.047814,8.439,19.297,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,10000,compas_pb,240074,2.419,0.0031,4.4e-05,0.01054,0.003274,0.013639,77.451,22.778,3599350,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,10000,compas_pb_zip,228795,2.538,0.009161,4.4e-05,0.011221,0.003335,0.020382,24.976,20.39,3840652,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,10000,compas_pb_zstd,227771,2.549,0.003329,2.9e-05,0.011655,0.002563,0.014983,68.43,19.543,3839561,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +pointcloud,10000,compas_msgpack,280093,2.073,0.003666,9.8e-05,0.026973,0.003116,0.03064,76.399,10.384,4570603,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +pointcloud,10000,compas_msgpack_zstd,250823,2.315,0.004733,6.9e-05,0.032582,0.000968,0.037315,52.994,7.698,4850729,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +pointcloud,100000,json,5804860,1.0,0.150705,0.001237,0.188525,0.001163,0.33923,38.518,30.791,42602609,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,json_zip,2792760,2.079,0.354503,0.005964,0.209641,0.018254,0.564144,7.878,13.322,42599930,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,100000,compas_pb,2400078,2.419,0.032003,0.000291,0.158647,0.010433,0.190649,74.996,15.128,35996478,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,100000,compas_pb_zip,2286030,2.539,0.094398,0.000759,0.176587,0.003583,0.270985,24.217,12.946,38397656,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,100000,compas_pb_zstd,2276982,2.549,0.034991,0.000747,0.170809,0.003774,0.2058,65.074,13.331,38396589,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +pointcloud,100000,compas_msgpack,2800095,2.073,0.049033,0.000188,0.353375,0.0107,0.402408,57.107,7.924,45598744,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +pointcloud,100000,compas_msgpack_zstd,2457514,2.362,0.082358,0.001446,0.371287,0.003603,0.453645,29.839,6.619,48398819,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +points,1000,json,145071,1.0,0.003946,0.00134,0.003612,0.000143,0.007557,36.768,40.168,512822,True,True,True,0.0,0.0,"compact text, lossless" +points,1000,json_zip,55949,2.593,0.006128,0.001679,0.00408,0.000252,0.010207,9.131,13.714,515327,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +points,1000,compas_pb,79015,1.836,0.003564,0.000193,0.005187,0.000245,0.008751,22.169,15.233,266342,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +points,1000,compas_pb_zip,26095,5.559,0.004203,0.000124,0.00512,0.000128,0.009323,6.209,5.097,346581,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +points,1000,compas_pb_zstd,24960,5.812,0.003914,0.000241,0.004912,0.000171,0.008827,6.377,5.081,345390,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +points,1000,compas_msgpack,105003,1.382,0.001722,0.001465,0.005296,0.000104,0.007018,60.973,19.826,824071,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +points,1000,compas_msgpack_zstd,51853,2.798,0.002833,0.0014,0.005195,0.00014,0.008029,18.301,9.981,931099,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +points,10000,json,1450530,1.0,0.03542,0.014215,0.037479,0.00484,0.072899,40.952,38.703,5170601,True,True,True,0.0,0.0,"compact text, lossless" +points,10000,json_zip,552776,2.624,0.059725,0.0159,0.039387,0.004675,0.099112,9.255,14.034,5173098,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +points,10000,compas_pb,790015,1.836,0.032246,0.000275,0.048519,0.003197,0.080765,24.5,16.283,2718662,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +points,10000,compas_pb_zip,258617,5.609,0.042655,0.001369,0.05043,0.000308,0.093085,6.063,5.128,3510433,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +points,10000,compas_pb_zstd,247395,5.863,0.036958,0.000165,0.048617,0.003018,0.085575,6.694,5.089,3508710,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +points,10000,compas_msgpack,1050003,1.381,0.016752,0.013633,0.061366,0.004546,0.078118,62.678,17.11,8455711,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +points,10000,compas_msgpack_zstd,511645,2.835,0.028419,0.013873,0.062845,0.00201,0.091264,18.004,8.141,9505747,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +spheres,1000,json,237252,1.0,0.007789,0.001879,0.038637,0.00021,0.046426,30.46,6.14,1630917,True,True,True,0.0,0.0,"compact text, lossless" +spheres,1000,json_zip,68288,3.474,0.009534,0.001652,0.039141,0.000165,0.048675,7.162,1.745,1633422,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +spheres,1000,compas_pb,115015,2.063,0.007303,0.000491,0.047104,0.00417,0.054408,15.748,2.442,1291821,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +spheres,1000,compas_pb_zip,35118,6.756,0.007768,0.000113,0.046415,0.00131,0.054182,4.521,0.757,1408292,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +spheres,1000,compas_pb_zstd,33203,7.145,0.007374,7.7e-05,0.045207,0.000251,0.052581,4.503,0.734,1406869,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +spheres,1000,compas_msgpack,204003,1.163,0.003768,0.00128,0.046801,0.000704,0.050569,54.14,4.359,2619323,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +spheres,1000,compas_msgpack_zstd,62218,3.813,0.004893,0.001743,0.045986,0.000181,0.050879,12.715,1.353,2823359,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +spheres,10000,json,2372345,1.0,0.068659,0.016699,0.411094,0.007129,0.479753,34.553,5.771,16334546,True,True,True,0.0,0.0,"compact text, lossless" +spheres,10000,json_zip,677372,3.502,0.100829,0.023523,0.412016,0.004245,0.512846,6.718,1.644,16337051,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +spheres,10000,compas_pb,1150015,2.063,0.067687,0.001746,0.477364,0.012154,0.54505,16.99,2.409,12960429,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +spheres,10000,compas_pb_zip,348595,6.805,0.081801,0.000708,0.47126,0.00317,0.553061,4.262,0.74,14111672,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +spheres,10000,compas_pb_zstd,334774,7.086,0.07759,0.000986,0.479162,0.004213,0.556753,4.315,0.699,14110477,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +spheres,10000,compas_msgpack,2040003,1.163,0.032219,0.015286,0.493436,0.017911,0.525655,63.317,4.134,26391451,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +spheres,10000,compas_msgpack_zstd,608979,3.896,0.050654,0.016311,0.516215,0.017076,0.56687,12.022,1.18,28431935,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +vectors,1000,json,146071,1.0,0.003896,0.001581,0.003872,0.000172,0.007768,37.493,37.727,513823,True,True,True,0.0,0.0,"compact text, lossless" +vectors,1000,json_zip,55991,2.609,0.00605,0.001626,0.004528,0.002722,0.010578,9.255,12.365,516328,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +vectors,1000,compas_pb,80015,1.826,0.003286,5e-05,0.005089,5.9e-05,0.008376,24.347,15.722,266345,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +vectors,1000,compas_pb_zip,26096,5.597,0.003884,0.000148,0.005128,3.5e-05,0.009012,6.719,5.088,347588,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +vectors,1000,compas_pb_zstd,24962,5.852,0.00377,7.8e-05,0.005034,1.9e-05,0.008804,6.621,4.959,346393,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +vectors,1000,compas_msgpack,106003,1.378,0.001812,0.001398,0.005427,0.000134,0.007238,58.509,19.534,825072,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +vectors,1000,compas_msgpack_zstd,51841,2.818,0.002835,0.001433,0.005518,0.000105,0.008353,18.288,9.395,931108,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +vectors,10000,json,1460530,1.0,0.035207,0.015179,0.038935,0.005051,0.074142,41.484,37.512,5180650,True,True,True,0.0,0.0,"compact text, lossless" +vectors,10000,json_zip,552978,2.641,0.062124,0.015071,0.041944,0.00591,0.104068,8.901,13.184,5183107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +vectors,10000,compas_pb,800015,1.826,0.033781,0.00066,0.050982,0.002816,0.084763,23.682,15.692,2718665,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +vectors,10000,compas_pb_zip,258630,5.647,0.039896,0.000318,0.051209,0.000264,0.091105,6.483,5.05,3519908,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +vectors,10000,compas_pb_zstd,249995,5.842,0.037993,0.000743,0.049877,0.003142,0.08787,6.58,5.012,3518713,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +vectors,10000,compas_msgpack,1060003,1.378,0.016991,0.013967,0.063531,0.006412,0.080522,62.386,16.685,8466176,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +vectors,10000,compas_msgpack_zstd,506817,2.882,0.031833,0.01724,0.070547,0.005589,0.10238,15.921,7.184,9526212,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" diff --git a/benchmarks/serialization/results/baseline_quick.html b/benchmarks/serialization/results/baseline_quick.html index 891c42370f33..0407be9315d9 100644 --- a/benchmarks/serialization/results/baseline_quick.html +++ b/benchmarks/serialization/results/baseline_quick.html @@ -77,4 +77,99 @@ .tile .sub { font-size: 11px; color: var(--muted); margin-top: 1px; } .win { color: var(--good); font-weight: 600; } h2.section { margin-top: 8px; } -

COMPAS serialization benchmark

generated 2026-07-10 00:41 · preset quick · repeat 5 · seed 42 · compas 2.15.0-b26fd518

Summary

On the largest payloads, compas_pb (protobuf: double + flat coordinate arrays) is the smallest and fastest option — up to 2.7× smaller and 1.8× faster to load than compact JSON, losslessly.

2.7× smaller
compas_pb vs JSON on the wire
best: mesh @ 10,000 elements
1.8× faster
compas_pb round-trip vs JSON
best: pointcloud @ 100,000 elements
3/3
subjects lossless (compas_pb)
exact round-trip of __data__
subjectelementssmallestvs JSONfastest round-tripvs JSONcompas_pb lossless
mesh10,000compas_pb_zip · 158.5 KB5.45×compas_pb · 49.7 ms1.26×✓ yes
mesh_attrs10,000compas_pb_zip · 273.3 KB4.21×json · 68.8 ms1.00×✓ yes
pointcloud100,000compas_pb_zip · 2.2 MB2.54×compas_pb · 187.0 ms1.80×✓ yes
json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, double + flat arrays (optimized)compas_pb_zip · protobuf binary, zip-compressed

mesh

Round-trip time
1,000 elements
json
5.3 ms
json_zip
7.3 ms
compas_pb
5.0 ms
compas_pb_zip
5.4 ms
10,000 elements
json
62.7 ms
json_zip
86.3 ms
compas_pb
49.7 ms
compas_pb_zip
56.8 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
32.2 KB
compas_pb_zip
16.0 KB
10,000 elements
json
864.1 KB
json_zip
238.1 KB
compas_pb
320.4 KB
compas_pb_zip
158.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.6 ms3.7 ms5.3 ms22.0471.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.5 ms3.8 ms7.3 ms7.4031.5 MB0✓ yes
1,000compas_pb32.2 KB2.493×1.6 ms3.4 ms5.0 ms9.75849.9 KB0✓ yes
1,000compas_pb_zip16.0 KB5.017×2.1 ms3.3 ms5.4 ms4.917883.5 KB0✓ yes
10,000json864.1 KB1.0×16.8 ms45.9 ms62.7 ms19.27915.3 MB0✓ yes
10,000json_zip238.1 KB3.629×39.0 ms47.3 ms86.3 ms5.15815.3 MB0✓ yes
10,000compas_pb320.4 KB2.697×15.9 ms33.8 ms49.7 ms9.7028.2 MB0✓ yes
10,000compas_pb_zip158.5 KB5.451×22.6 ms34.3 ms56.8 ms4.7348.5 MB0✓ yes

mesh_attrs

Round-trip time
1,000 elements
json
5.7 ms
json_zip
8.2 ms
compas_pb
12.5 ms
compas_pb_zip
13.7 ms
10,000 elements
json
68.8 ms
json_zip
99.6 ms
compas_pb
129.7 ms
compas_pb_zip
142.9 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
65.1 KB
compas_pb_zip
27.7 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
651.3 KB
compas_pb_zip
273.3 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.9 ms3.8 ms5.7 ms29.2211.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.3 ms3.9 ms8.2 ms9.8261.6 MB0✓ yes
1,000compas_pb65.1 KB1.682×5.8 ms6.7 ms12.5 ms9.9721.2 MB0✓ yes
1,000compas_pb_zip27.7 KB3.952×6.7 ms6.9 ms13.7 ms4.0941.3 MB0✓ yes
10,000json1.1 MB1.0×21.1 ms47.7 ms68.8 ms24.68715.8 MB0✓ yes
10,000json_zip338.9 KB3.393×51.7 ms48.0 ms99.6 ms7.23715.8 MB0✓ yes
10,000compas_pb651.3 KB1.765×57.7 ms72.0 ms129.7 ms9.26512.0 MB0✓ yes
10,000compas_pb_zip273.3 KB4.208×69.7 ms73.2 ms142.9 ms3.82312.6 MB0✓ yes

pointcloud

Round-trip time
10,000 elements
json
28.1 ms
json_zip
47.8 ms
compas_pb
13.8 ms
compas_pb_zip
20.1 ms
100,000 elements
json
337.0 ms
json_zip
529.0 ms
compas_pb
187.0 ms
compas_pb_zip
258.7 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
234.5 KB
compas_pb_zip
223.5 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
2.3 MB
compas_pb_zip
2.2 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.7 ms14.4 ms28.1 ms40.2694.1 MB0✓ yes
10,000json_zip274.1 KB2.068×33.4 ms14.3 ms47.8 ms19.574.1 MB0✓ yes
10,000compas_pb234.5 KB2.418×3.3 ms10.6 ms13.8 ms22.6823.4 MB0✓ yes
10,000compas_pb_zip223.5 KB2.537×9.2 ms10.9 ms20.1 ms20.983.7 MB0✓ yes
100,000json5.5 MB1.0×150.2 ms186.8 ms337.0 ms31.07640.6 MB0✓ yes
100,000json_zip2.7 MB2.079×348.0 ms181.0 ms529.0 ms15.43240.6 MB0✓ yes
100,000compas_pb2.3 MB2.419×32.3 ms154.7 ms187.0 ms15.51434.3 MB0✓ yes
100,000compas_pb_zip2.2 MB2.539×93.9 ms164.8 ms258.7 ms13.87536.6 MB0✓ yes
\ No newline at end of file +.controls { margin: 14px 0 4px; display: flex; align-items: center; gap: 12px; } +.controls-label { font-size: 13px; color: var(--text-secondary); } +.segmented { display: inline-flex; background: var(--track); border: 1px solid var(--border); + border-radius: 9px; padding: 2px; gap: 2px; } +.segmented button { font: inherit; font-size: 13px; color: var(--text-secondary); cursor: pointer; + background: transparent; border: 0; border-radius: 7px; padding: 5px 14px; line-height: 1.4; } +.segmented button:hover { color: var(--text-primary); } +.segmented button.active { background: var(--surface); color: var(--text-primary); font-weight: 600; + box-shadow: 0 1px 2px rgba(0,0,0,0.10); } +.tile .rng { font-size: 11px; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; } +

COMPAS serialization benchmark

generated 2026-07-10 12:35 · preset quick · repeat 3 · seed 42 · compas 2.15.0-6fec8b70

Show formats
json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, double + flat arrays (optimized)compas_pb_zip · protobuf binary, zip-compressedcompas_pb_zstd · protobuf binary, zstandard-compressedcompas_msgpack · msgpack over the JSON-shape tree (Kumiki-style)compas_msgpack_zstd · msgpack, zstandard-compressed

boxes

Round-trip time
1,000 elements
json
49.0 ms
json_zip
52.2 ms
compas_pb
52.3 ms
compas_pb_zip
54.9 ms
compas_pb_zstd
53.0 ms
compas_msgpack
49.9 ms
compas_msgpack_zstd
52.5 ms
10,000 elements
json
499.4 ms
json_zip
550.3 ms
compas_pb
552.8 ms
compas_pb_zip
564.4 ms
compas_pb_zstd
560.9 ms
compas_msgpack
549.0 ms
compas_msgpack_zstd
557.6 ms
Wire size
1,000 elements
json
278.9 KB
json_zip
87.8 KB
compas_pb
127.9 KB
compas_pb_zip
51.1 KB
compas_pb_zstd
48.9 KB
compas_msgpack
224.6 KB
compas_msgpack_zstd
77.6 KB
10,000 elements
json
2.7 MB
json_zip
871.2 KB
compas_pb
1.2 MB
compas_pb_zip
508.7 KB
compas_pb_zstd
485.5 KB
compas_msgpack
2.2 MB
compas_msgpack_zstd
776.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json278.9 KB1.0×7.8 ms41.2 ms49.0 ms6.9331.6 MB0✓ yes
1,000json_zip87.8 KB3.178×11.6 ms40.6 ms52.2 ms2.2141.6 MB0✓ yes
1,000compas_pb127.9 KB2.18×6.7 ms45.6 ms52.3 ms2.8761.3 MB0✓ yes
1,000compas_pb_zip51.1 KB5.46×8.4 ms46.6 ms54.9 ms1.1231.4 MB0✓ yes
1,000compas_pb_zstd48.9 KB5.706×7.7 ms45.3 ms53.0 ms1.1041.4 MB0✓ yes
1,000compas_msgpack224.6 KB1.242×3.4 ms46.5 ms49.9 ms4.952.5 MB0✓ yes
1,000compas_msgpack_zstd77.6 KB3.595×5.6 ms46.9 ms52.5 ms1.6932.8 MB0✓ yes
10,000json2.7 MB1.0×83.9 ms415.5 ms499.4 ms6.87216.5 MB0✓ yes
10,000json_zip871.2 KB3.201×118.6 ms431.7 ms550.3 ms2.06616.5 MB0✓ yes
10,000compas_pb1.2 MB2.18×70.7 ms482.1 ms552.8 ms2.71712.8 MB0✓ yes
10,000compas_pb_zip508.7 KB5.482×84.4 ms480.0 ms564.4 ms1.08514.1 MB0✓ yes
10,000compas_pb_zstd485.5 KB5.743×79.1 ms481.8 ms560.9 ms1.03214.1 MB0✓ yes
10,000compas_msgpack2.2 MB1.241×35.1 ms513.9 ms549.0 ms4.47625.6 MB0✓ yes
10,000compas_msgpack_zstd776.7 KB3.59×57.0 ms500.6 ms557.6 ms1.58927.8 MB0✓ yes

circles

Round-trip time
1,000 elements
json
45.2 ms
json_zip
49.1 ms
compas_pb
54.1 ms
compas_pb_zip
56.6 ms
compas_pb_zstd
55.2 ms
compas_msgpack
51.4 ms
compas_msgpack_zstd
50.6 ms
10,000 elements
json
497.7 ms
json_zip
528.4 ms
compas_pb
568.4 ms
compas_pb_zip
602.9 ms
compas_pb_zstd
593.8 ms
compas_msgpack
531.8 ms
compas_msgpack_zstd
545.3 ms
Wire size
1,000 elements
json
231.6 KB
json_zip
66.7 KB
compas_pb
159.2 KB
compas_pb_zip
62.0 KB
compas_pb_zstd
60.5 KB
compas_msgpack
199.2 KB
compas_msgpack_zstd
60.7 KB
10,000 elements
json
2.3 MB
json_zip
661.6 KB
compas_pb
1.6 MB
compas_pb_zip
616.8 KB
compas_pb_zstd
592.2 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
594.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json231.6 KB1.0×6.6 ms38.6 ms45.2 ms6.1431.5 MB0✓ yes
1,000json_zip66.7 KB3.474×9.6 ms39.5 ms49.1 ms1.731.5 MB0✓ yes
1,000compas_pb159.2 KB1.455×7.6 ms46.5 ms54.1 ms3.5081.3 MB0✓ yes
1,000compas_pb_zip62.0 KB3.736×9.7 ms46.8 ms56.6 ms1.3561.5 MB0✓ yes
1,000compas_pb_zstd60.5 KB3.828×9.2 ms46.0 ms55.2 ms1.3471.5 MB0✓ yes
1,000compas_msgpack199.2 KB1.163×3.6 ms47.8 ms51.4 ms4.2682.4 MB0✓ yes
1,000compas_msgpack_zstd60.7 KB3.816×4.8 ms45.9 ms50.6 ms1.3552.6 MB0✓ yes
10,000json2.3 MB1.0×66.4 ms431.3 ms497.7 ms5.514.7 MB0✓ yes
10,000json_zip661.6 KB3.501×97.3 ms431.1 ms528.4 ms1.57214.7 MB0✓ yes
10,000compas_pb1.6 MB1.455×78.1 ms490.3 ms568.4 ms3.32413.0 MB0✓ yes
10,000compas_pb_zip616.8 KB3.756×101.4 ms501.6 ms602.9 ms1.25914.6 MB0✓ yes
10,000compas_pb_zstd592.2 KB3.912×91.1 ms502.7 ms593.8 ms1.20614.6 MB0✓ yes
10,000compas_msgpack1.9 MB1.163×32.6 ms499.2 ms531.8 ms4.08724.3 MB0✓ yes
10,000compas_msgpack_zstd594.7 KB3.896×48.8 ms496.5 ms545.3 ms1.22726.3 MB0✓ yes

frames

Round-trip time
1,000 elements
json
29.3 ms
json_zip
35.8 ms
compas_pb
38.4 ms
compas_pb_zip
35.0 ms
compas_pb_zstd
32.8 ms
compas_msgpack
28.4 ms
compas_msgpack_zstd
29.9 ms
10,000 elements
json
296.0 ms
json_zip
357.4 ms
compas_pb
329.0 ms
compas_pb_zip
368.7 ms
compas_pb_zstd
348.6 ms
compas_msgpack
320.6 ms
compas_msgpack_zstd
340.8 ms
Wire size
1,000 elements
json
288.9 KB
json_zip
107.2 KB
compas_pb
137.7 KB
compas_pb_zip
69.8 KB
compas_pb_zstd
68.1 KB
compas_msgpack
175.8 KB
compas_msgpack_zstd
94.4 KB
10,000 elements
json
2.8 MB
json_zip
1.0 MB
compas_pb
1.3 MB
compas_pb_zip
695.9 KB
compas_pb_zstd
690.5 KB
compas_msgpack
1.7 MB
compas_msgpack_zstd
941.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json288.9 KB1.0×7.7 ms21.6 ms29.3 ms13.6871.3 MB4.4e-16✗ no
1,000json_zip107.2 KB2.696×14.5 ms21.3 ms35.8 ms5.1541.3 MB4.4e-16✗ no
1,000compas_pb137.7 KB2.098×5.5 ms32.9 ms38.4 ms4.287964.4 KB4.4e-16✗ no
1,000compas_pb_zip69.8 KB4.14×8.5 ms26.5 ms35.0 ms2.6951.1 MB4.4e-16✗ no
1,000compas_pb_zstd68.1 KB4.241×6.9 ms26.0 ms32.8 ms2.6871.1 MB4.4e-16✗ no
1,000compas_msgpack175.8 KB1.644×2.9 ms25.5 ms28.4 ms7.062.0 MB4.4e-16✗ no
1,000compas_msgpack_zstd94.4 KB3.06×4.7 ms25.3 ms29.9 ms3.8282.2 MB4.4e-16✗ no
10,000json2.8 MB1.0×73.2 ms222.8 ms296.0 ms13.28413.2 MB5.6e-16✗ no
10,000json_zip1.0 MB2.715×134.5 ms222.9 ms357.4 ms4.89113.2 MB5.6e-16✗ no
10,000compas_pb1.3 MB2.099×55.5 ms273.5 ms329.0 ms5.1559.5 MB5.6e-16✗ no
10,000compas_pb_zip695.9 KB4.153×87.0 ms281.7 ms368.7 ms2.5310.8 MB5.6e-16✗ no
10,000compas_pb_zstd690.5 KB4.186×73.7 ms274.9 ms348.6 ms2.57210.8 MB5.6e-16✗ no
10,000compas_msgpack1.7 MB1.644×29.5 ms291.1 ms320.6 ms6.18320.0 MB5.6e-16✗ no
10,000compas_msgpack_zstd941.5 KB3.07×57.4 ms283.4 ms340.8 ms3.40221.8 MB5.6e-16✗ no

graph

Round-trip time
1,000 elements
json
15.4 ms
json_zip
15.9 ms
compas_pb
8.1 ms
compas_pb_zip
8.7 ms
compas_pb_zstd
8.4 ms
compas_msgpack
15.3 ms
compas_msgpack_zstd
15.9 ms
10,000 elements
json
149.2 ms
json_zip
170.9 ms
compas_pb
77.5 ms
compas_pb_zip
88.1 ms
compas_pb_zstd
81.6 ms
compas_msgpack
176.7 ms
compas_msgpack_zstd
179.7 ms
Wire size
1,000 elements
json
74.9 KB
json_zip
23.8 KB
compas_pb
36.3 KB
compas_pb_zip
15.1 KB
compas_pb_zstd
15.7 KB
compas_msgpack
52.6 KB
compas_msgpack_zstd
17.3 KB
10,000 elements
json
775.1 KB
json_zip
208.4 KB
compas_pb
360.2 KB
compas_pb_zip
139.4 KB
compas_pb_zstd
181.5 KB
compas_msgpack
551.6 KB
compas_msgpack_zstd
116.2 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json74.9 KB1.0×1.8 ms13.7 ms15.4 ms5.6051.8 MB0✓ yes
1,000json_zip23.8 KB3.153×3.5 ms12.5 ms15.9 ms1.9521.9 MB0✓ yes
1,000compas_pb36.3 KB2.064×4.0 ms4.0 ms8.1 ms9.2111.1 MB0✓ yes
1,000compas_pb_zip15.1 KB4.961×4.7 ms4.0 ms8.7 ms3.8891.1 MB0✓ yes
1,000compas_pb_zstd15.7 KB4.774×4.4 ms4.0 ms8.4 ms3.9971.1 MB0✓ yes
1,000compas_msgpack52.6 KB1.424×0.6 ms14.7 ms15.3 ms3.6772.4 MB0✓ yes
1,000compas_msgpack_zstd17.3 KB4.323×1.2 ms14.7 ms15.9 ms1.2082.5 MB0✓ yes
10,000json775.1 KB1.0×17.0 ms132.3 ms149.2 ms5.99918.2 MB0✓ yes
10,000json_zip208.4 KB3.719×33.9 ms137.0 ms170.9 ms1.55718.1 MB0✓ yes
10,000compas_pb360.2 KB2.152×39.9 ms37.6 ms77.5 ms9.80710.5 MB0✓ yes
10,000compas_pb_zip139.4 KB5.561×48.0 ms40.1 ms88.1 ms3.56210.9 MB0✓ yes
10,000compas_pb_zstd181.5 KB4.271×43.5 ms38.1 ms81.6 ms4.88310.9 MB0✓ yes
10,000compas_msgpack551.6 KB1.405×8.5 ms168.1 ms176.7 ms3.3624.0 MB0✓ yes
10,000compas_msgpack_zstd116.2 KB6.672×11.1 ms168.6 ms179.7 ms0.70624.5 MB0✓ yes

lines

Round-trip time
1,000 elements
json
15.6 ms
json_zip
20.2 ms
compas_pb
18.7 ms
compas_pb_zip
20.8 ms
compas_pb_zstd
19.8 ms
compas_msgpack
16.2 ms
compas_msgpack_zstd
18.0 ms
10,000 elements
json
171.6 ms
json_zip
214.9 ms
compas_pb
202.3 ms
compas_pb_zip
218.1 ms
compas_pb_zstd
207.7 ms
compas_msgpack
180.5 ms
compas_msgpack_zstd
208.9 ms
Wire size
1,000 elements
json
213.0 KB
json_zip
85.0 KB
compas_pb
106.5 KB
compas_pb_zip
50.6 KB
compas_pb_zstd
49.0 KB
compas_msgpack
139.7 KB
compas_msgpack_zstd
76.7 KB
10,000 elements
json
2.1 MB
json_zip
842.7 KB
compas_pb
1.0 MB
compas_pb_zip
503.6 KB
compas_pb_zstd
486.6 KB
compas_msgpack
1.4 MB
compas_msgpack_zstd
751.3 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json213.0 KB1.0×7.6 ms8.0 ms15.6 ms27.1841017.5 KB0✓ yes
1,000json_zip85.0 KB2.507×11.7 ms8.5 ms20.2 ms10.2251020.4 KB0✓ yes
1,000compas_pb106.5 KB2.001×7.0 ms11.7 ms18.7 ms9.308705.9 KB0✓ yes
1,000compas_pb_zip50.6 KB4.211×8.8 ms12.1 ms20.8 ms4.291813.6 KB0✓ yes
1,000compas_pb_zstd49.0 KB4.348×7.9 ms11.9 ms19.8 ms4.216812.4 KB0✓ yes
1,000compas_msgpack139.7 KB1.525×4.6 ms11.6 ms16.2 ms12.2781.6 MB0✓ yes
1,000compas_msgpack_zstd76.7 KB2.777×6.1 ms11.9 ms18.0 ms6.6211.7 MB0✓ yes
10,000json2.1 MB1.0×81.3 ms90.4 ms171.6 ms24.13210.0 MB0✓ yes
10,000json_zip842.7 KB2.528×118.2 ms96.7 ms214.9 ms8.92710.0 MB0✓ yes
10,000compas_pb1.0 MB2.001×73.8 ms128.5 ms202.3 ms8.4826.9 MB0✓ yes
10,000compas_pb_zip503.6 KB4.23×87.3 ms130.8 ms218.1 ms3.9438.0 MB0✓ yes
10,000compas_pb_zstd486.6 KB4.378×78.5 ms129.2 ms207.7 ms3.8568.0 MB0✓ yes
10,000compas_msgpack1.4 MB1.525×48.0 ms132.5 ms180.5 ms10.79216.1 MB0✓ yes
10,000compas_msgpack_zstd751.3 KB2.835×67.8 ms141.1 ms208.9 ms5.45217.4 MB0✓ yes

mesh

Round-trip time
1,000 elements
json
5.1 ms
json_zip
7.3 ms
compas_pb
5.0 ms
compas_pb_zip
5.7 ms
compas_pb_zstd
5.4 ms
compas_msgpack
8.0 ms
compas_msgpack_zstd
8.5 ms
10,000 elements
json
60.6 ms
json_zip
83.0 ms
compas_pb
51.6 ms
compas_pb_zip
58.4 ms
compas_pb_zstd
53.2 ms
compas_msgpack
93.2 ms
compas_msgpack_zstd
95.5 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
32.1 KB
compas_pb_zip
15.9 KB
compas_pb_zstd
15.8 KB
compas_msgpack
57.3 KB
compas_msgpack_zstd
24.5 KB
10,000 elements
json
864.1 KB
json_zip
238.2 KB
compas_pb
320.3 KB
compas_pb_zip
158.5 KB
compas_pb_zstd
168.6 KB
compas_msgpack
606.5 KB
compas_msgpack_zstd
198.8 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.5 ms3.6 ms5.1 ms22.8231.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.5 ms3.8 ms7.3 ms7.4691.5 MB0✓ yes
1,000compas_pb32.1 KB2.496×1.7 ms3.3 ms5.0 ms10.035857.4 KB0✓ yes
1,000compas_pb_zip15.9 KB5.031×2.3 ms3.4 ms5.7 ms4.813890.9 KB0✓ yes
1,000compas_pb_zstd15.8 KB5.07×2.1 ms3.3 ms5.4 ms4.881889.6 KB0✓ yes
1,000compas_msgpack57.3 KB1.4×0.4 ms7.5 ms8.0 ms7.7892.0 MB0✓ yes
1,000compas_msgpack_zstd24.5 KB3.269×1.0 ms7.5 ms8.5 ms3.3642.0 MB0✓ yes
10,000json864.1 KB1.0×16.4 ms44.2 ms60.6 ms20.03115.3 MB0✓ yes
10,000json_zip238.2 KB3.629×39.1 ms43.9 ms83.0 ms5.56115.3 MB0✓ yes
10,000compas_pb320.3 KB2.698×17.0 ms34.5 ms51.6 ms9.4998.3 MB0✓ yes
10,000compas_pb_zip158.5 KB5.453×23.8 ms34.5 ms58.4 ms4.6978.6 MB0✓ yes
10,000compas_pb_zstd168.6 KB5.125×19.9 ms33.3 ms53.2 ms5.1798.6 MB0✓ yes
10,000compas_msgpack606.5 KB1.425×4.9 ms88.3 ms93.2 ms7.03319.6 MB0✓ yes
10,000compas_msgpack_zstd198.8 KB4.348×8.4 ms87.1 ms95.5 ms2.33720.2 MB0✓ yes

mesh_attrs

Round-trip time
1,000 elements
json
5.9 ms
json_zip
8.4 ms
compas_pb
5.6 ms
compas_pb_zip
6.1 ms
compas_pb_zstd
5.7 ms
compas_msgpack
8.5 ms
compas_msgpack_zstd
9.4 ms
10,000 elements
json
68.4 ms
json_zip
102.8 ms
compas_pb
55.2 ms
compas_pb_zip
69.9 ms
compas_pb_zstd
56.8 ms
compas_msgpack
97.2 ms
compas_msgpack_zstd
100.0 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
40.2 KB
compas_pb_zip
23.7 KB
compas_pb_zstd
23.7 KB
compas_msgpack
74.3 KB
compas_msgpack_zstd
33.0 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
398.5 KB
compas_pb_zip
232.9 KB
compas_pb_zstd
233.3 KB
compas_msgpack
772.5 KB
compas_msgpack_zstd
275.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×2.0 ms3.9 ms5.9 ms28.6391.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.4 ms3.9 ms8.4 ms9.6651.6 MB0✓ yes
1,000compas_pb40.2 KB2.726×2.0 ms3.6 ms5.6 ms11.475945.2 KB0✓ yes
1,000compas_pb_zip23.7 KB4.611×2.6 ms3.5 ms6.1 ms6.92986.7 KB0✓ yes
1,000compas_pb_zstd23.7 KB4.617×2.3 ms3.4 ms5.7 ms7.169985.4 KB0✓ yes
1,000compas_msgpack74.3 KB1.474×0.4 ms8.0 ms8.5 ms9.4932.0 MB0✓ yes
1,000compas_msgpack_zstd33.0 KB3.317×1.3 ms8.1 ms9.4 ms4.1722.1 MB0✓ yes
10,000json1.1 MB1.0×19.8 ms48.6 ms68.4 ms24.22415.8 MB0✓ yes
10,000json_zip338.9 KB3.393×51.3 ms51.5 ms102.8 ms6.73915.8 MB0✓ yes
10,000compas_pb398.5 KB2.886×20.0 ms35.2 ms55.2 ms11.5999.2 MB0✓ yes
10,000compas_pb_zip232.9 KB4.936×28.8 ms41.1 ms69.9 ms5.8039.5 MB0✓ yes
10,000compas_pb_zstd233.3 KB4.929×22.3 ms34.5 ms56.8 ms6.9259.5 MB0✓ yes
10,000compas_msgpack772.5 KB1.489×4.5 ms92.7 ms97.2 ms8.53819.9 MB0✓ yes
10,000compas_msgpack_zstd275.5 KB4.175×10.2 ms89.9 ms100.0 ms3.13820.6 MB0✓ yes

planes

Round-trip time
1,000 elements
json
13.7 ms
json_zip
18.8 ms
compas_pb
17.7 ms
compas_pb_zip
18.7 ms
compas_pb_zstd
18.9 ms
compas_msgpack
15.0 ms
compas_msgpack_zstd
16.4 ms
10,000 elements
json
148.8 ms
json_zip
200.9 ms
compas_pb
176.4 ms
compas_pb_zip
202.9 ms
compas_pb_zstd
190.3 ms
compas_msgpack
157.6 ms
compas_msgpack_zstd
181.0 ms
Wire size
1,000 elements
json
219.9 KB
json_zip
85.4 KB
compas_pb
107.4 KB
compas_pb_zip
51.1 KB
compas_pb_zstd
49.4 KB
compas_msgpack
143.6 KB
compas_msgpack_zstd
77.5 KB
10,000 elements
json
2.1 MB
json_zip
846.3 KB
compas_pb
1.0 MB
compas_pb_zip
508.5 KB
compas_pb_zstd
497.0 KB
compas_msgpack
1.4 MB
compas_msgpack_zstd
761.9 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json219.9 KB1.0×5.4 ms8.3 ms13.7 ms27.1181.0 MB2.2e-16✗ no
1,000json_zip85.4 KB2.574×10.0 ms8.8 ms18.8 ms9.9031.0 MB2.2e-16✗ no
1,000compas_pb107.4 KB2.046×4.7 ms13.0 ms17.7 ms8.444705.7 KB2.2e-16✗ no
1,000compas_pb_zip51.1 KB4.305×6.1 ms12.6 ms18.7 ms4.138814.4 KB2.2e-16✗ no
1,000compas_pb_zstd49.4 KB4.448×5.7 ms13.2 ms18.9 ms3.841813.2 KB2.2e-16✗ no
1,000compas_msgpack143.6 KB1.532×2.5 ms12.4 ms15.0 ms11.8111.6 MB2.2e-16✗ no
1,000compas_msgpack_zstd77.5 KB2.837×4.0 ms12.3 ms16.4 ms6.4351.7 MB2.2e-16✗ no
10,000json2.1 MB1.0×54.7 ms94.1 ms148.8 ms23.92910.0 MB2.2e-16✗ no
10,000json_zip846.3 KB2.599×100.5 ms100.5 ms200.9 ms8.62610.0 MB2.2e-16✗ no
10,000compas_pb1.0 MB2.047×46.0 ms130.4 ms176.4 ms8.4386.9 MB2.2e-16✗ no
10,000compas_pb_zip508.5 KB4.325×62.1 ms140.8 ms202.9 ms3.6998.0 MB2.2e-16✗ no
10,000compas_pb_zstd497.0 KB4.425×56.2 ms134.1 ms190.3 ms3.7958.0 MB2.2e-16✗ no
10,000compas_msgpack1.4 MB1.532×24.2 ms133.4 ms157.6 ms11.0216.1 MB2.2e-16✗ no
10,000compas_msgpack_zstd761.9 KB2.887×39.6 ms141.4 ms181.0 ms5.51817.5 MB2.2e-16✗ no

pointcloud

Round-trip time
10,000 elements
json
26.6 ms
json_zip
47.8 ms
compas_pb
13.6 ms
compas_pb_zip
20.4 ms
compas_pb_zstd
15.0 ms
compas_msgpack
30.6 ms
compas_msgpack_zstd
37.3 ms
100,000 elements
json
339.2 ms
json_zip
564.1 ms
compas_pb
190.6 ms
compas_pb_zip
271.0 ms
compas_pb_zstd
205.8 ms
compas_msgpack
402.4 ms
compas_msgpack_zstd
453.6 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
234.4 KB
compas_pb_zip
223.4 KB
compas_pb_zstd
222.4 KB
compas_msgpack
273.5 KB
compas_msgpack_zstd
244.9 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
2.3 MB
compas_pb_zip
2.2 MB
compas_pb_zstd
2.2 MB
compas_msgpack
2.7 MB
compas_msgpack_zstd
2.3 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.3 ms13.3 ms26.6 ms43.684.1 MB0✓ yes
10,000json_zip274.1 KB2.068×33.3 ms14.5 ms47.8 ms19.2974.1 MB0✓ yes
10,000compas_pb234.4 KB2.419×3.1 ms10.5 ms13.6 ms22.7783.4 MB0✓ yes
10,000compas_pb_zip223.4 KB2.538×9.2 ms11.2 ms20.4 ms20.393.7 MB0✓ yes
10,000compas_pb_zstd222.4 KB2.549×3.3 ms11.7 ms15.0 ms19.5433.7 MB0✓ yes
10,000compas_msgpack273.5 KB2.073×3.7 ms27.0 ms30.6 ms10.3844.4 MB0✓ yes
10,000compas_msgpack_zstd244.9 KB2.315×4.7 ms32.6 ms37.3 ms7.6984.6 MB0✓ yes
100,000json5.5 MB1.0×150.7 ms188.5 ms339.2 ms30.79140.6 MB0✓ yes
100,000json_zip2.7 MB2.079×354.5 ms209.6 ms564.1 ms13.32240.6 MB0✓ yes
100,000compas_pb2.3 MB2.419×32.0 ms158.6 ms190.6 ms15.12834.3 MB0✓ yes
100,000compas_pb_zip2.2 MB2.539×94.4 ms176.6 ms271.0 ms12.94636.6 MB0✓ yes
100,000compas_pb_zstd2.2 MB2.549×35.0 ms170.8 ms205.8 ms13.33136.6 MB0✓ yes
100,000compas_msgpack2.7 MB2.073×49.0 ms353.4 ms402.4 ms7.92443.5 MB0✓ yes
100,000compas_msgpack_zstd2.3 MB2.362×82.4 ms371.3 ms453.6 ms6.61946.2 MB0✓ yes

points

Round-trip time
1,000 elements
json
7.6 ms
json_zip
10.2 ms
compas_pb
8.8 ms
compas_pb_zip
9.3 ms
compas_pb_zstd
8.8 ms
compas_msgpack
7.0 ms
compas_msgpack_zstd
8.0 ms
10,000 elements
json
72.9 ms
json_zip
99.1 ms
compas_pb
80.8 ms
compas_pb_zip
93.1 ms
compas_pb_zstd
85.6 ms
compas_msgpack
78.1 ms
compas_msgpack_zstd
91.3 ms
Wire size
1,000 elements
json
141.7 KB
json_zip
54.6 KB
compas_pb
77.2 KB
compas_pb_zip
25.5 KB
compas_pb_zstd
24.4 KB
compas_msgpack
102.5 KB
compas_msgpack_zstd
50.6 KB
10,000 elements
json
1.4 MB
json_zip
539.8 KB
compas_pb
771.5 KB
compas_pb_zip
252.6 KB
compas_pb_zstd
241.6 KB
compas_msgpack
1.0 MB
compas_msgpack_zstd
499.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json141.7 KB1.0×3.9 ms3.6 ms7.6 ms40.168500.8 KB0✓ yes
1,000json_zip54.6 KB2.593×6.1 ms4.1 ms10.2 ms13.714503.2 KB0✓ yes
1,000compas_pb77.2 KB1.836×3.6 ms5.2 ms8.8 ms15.233260.1 KB0✓ yes
1,000compas_pb_zip25.5 KB5.559×4.2 ms5.1 ms9.3 ms5.097338.5 KB0✓ yes
1,000compas_pb_zstd24.4 KB5.812×3.9 ms4.9 ms8.8 ms5.081337.3 KB0✓ yes
1,000compas_msgpack102.5 KB1.382×1.7 ms5.3 ms7.0 ms19.826804.8 KB0✓ yes
1,000compas_msgpack_zstd50.6 KB2.798×2.8 ms5.2 ms8.0 ms9.981909.3 KB0✓ yes
10,000json1.4 MB1.0×35.4 ms37.5 ms72.9 ms38.7034.9 MB0✓ yes
10,000json_zip539.8 KB2.624×59.7 ms39.4 ms99.1 ms14.0344.9 MB0✓ yes
10,000compas_pb771.5 KB1.836×32.2 ms48.5 ms80.8 ms16.2832.6 MB0✓ yes
10,000compas_pb_zip252.6 KB5.609×42.7 ms50.4 ms93.1 ms5.1283.3 MB0✓ yes
10,000compas_pb_zstd241.6 KB5.863×37.0 ms48.6 ms85.6 ms5.0893.3 MB0✓ yes
10,000compas_msgpack1.0 MB1.381×16.8 ms61.4 ms78.1 ms17.118.1 MB0✓ yes
10,000compas_msgpack_zstd499.7 KB2.835×28.4 ms62.8 ms91.3 ms8.1419.1 MB0✓ yes

spheres

Round-trip time
1,000 elements
json
46.4 ms
json_zip
48.7 ms
compas_pb
54.4 ms
compas_pb_zip
54.2 ms
compas_pb_zstd
52.6 ms
compas_msgpack
50.6 ms
compas_msgpack_zstd
50.9 ms
10,000 elements
json
479.8 ms
json_zip
512.8 ms
compas_pb
545.1 ms
compas_pb_zip
553.1 ms
compas_pb_zstd
556.8 ms
compas_msgpack
525.7 ms
compas_msgpack_zstd
566.9 ms
Wire size
1,000 elements
json
231.7 KB
json_zip
66.7 KB
compas_pb
112.3 KB
compas_pb_zip
34.3 KB
compas_pb_zstd
32.4 KB
compas_msgpack
199.2 KB
compas_msgpack_zstd
60.8 KB
10,000 elements
json
2.3 MB
json_zip
661.5 KB
compas_pb
1.1 MB
compas_pb_zip
340.4 KB
compas_pb_zstd
326.9 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
594.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json231.7 KB1.0×7.8 ms38.6 ms46.4 ms6.141.6 MB0✓ yes
1,000json_zip66.7 KB3.474×9.5 ms39.1 ms48.7 ms1.7451.6 MB0✓ yes
1,000compas_pb112.3 KB2.063×7.3 ms47.1 ms54.4 ms2.4421.2 MB0✓ yes
1,000compas_pb_zip34.3 KB6.756×7.8 ms46.4 ms54.2 ms0.7571.3 MB0✓ yes
1,000compas_pb_zstd32.4 KB7.145×7.4 ms45.2 ms52.6 ms0.7341.3 MB0✓ yes
1,000compas_msgpack199.2 KB1.163×3.8 ms46.8 ms50.6 ms4.3592.5 MB0✓ yes
1,000compas_msgpack_zstd60.8 KB3.813×4.9 ms46.0 ms50.9 ms1.3532.7 MB0✓ yes
10,000json2.3 MB1.0×68.7 ms411.1 ms479.8 ms5.77115.6 MB0✓ yes
10,000json_zip661.5 KB3.502×100.8 ms412.0 ms512.8 ms1.64415.6 MB0✓ yes
10,000compas_pb1.1 MB2.063×67.7 ms477.4 ms545.1 ms2.40912.4 MB0✓ yes
10,000compas_pb_zip340.4 KB6.805×81.8 ms471.3 ms553.1 ms0.7413.5 MB0✓ yes
10,000compas_pb_zstd326.9 KB7.086×77.6 ms479.2 ms556.8 ms0.69913.5 MB0✓ yes
10,000compas_msgpack1.9 MB1.163×32.2 ms493.4 ms525.7 ms4.13425.2 MB0✓ yes
10,000compas_msgpack_zstd594.7 KB3.896×50.7 ms516.2 ms566.9 ms1.1827.1 MB0✓ yes

vectors

Round-trip time
1,000 elements
json
7.8 ms
json_zip
10.6 ms
compas_pb
8.4 ms
compas_pb_zip
9.0 ms
compas_pb_zstd
8.8 ms
compas_msgpack
7.2 ms
compas_msgpack_zstd
8.4 ms
10,000 elements
json
74.1 ms
json_zip
104.1 ms
compas_pb
84.8 ms
compas_pb_zip
91.1 ms
compas_pb_zstd
87.9 ms
compas_msgpack
80.5 ms
compas_msgpack_zstd
102.4 ms
Wire size
1,000 elements
json
142.6 KB
json_zip
54.7 KB
compas_pb
78.1 KB
compas_pb_zip
25.5 KB
compas_pb_zstd
24.4 KB
compas_msgpack
103.5 KB
compas_msgpack_zstd
50.6 KB
10,000 elements
json
1.4 MB
json_zip
540.0 KB
compas_pb
781.3 KB
compas_pb_zip
252.6 KB
compas_pb_zstd
244.1 KB
compas_msgpack
1.0 MB
compas_msgpack_zstd
494.9 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json142.6 KB1.0×3.9 ms3.9 ms7.8 ms37.727501.8 KB0✓ yes
1,000json_zip54.7 KB2.609×6.0 ms4.5 ms10.6 ms12.365504.2 KB0✓ yes
1,000compas_pb78.1 KB1.826×3.3 ms5.1 ms8.4 ms15.722260.1 KB0✓ yes
1,000compas_pb_zip25.5 KB5.597×3.9 ms5.1 ms9.0 ms5.088339.4 KB0✓ yes
1,000compas_pb_zstd24.4 KB5.852×3.8 ms5.0 ms8.8 ms4.959338.3 KB0✓ yes
1,000compas_msgpack103.5 KB1.378×1.8 ms5.4 ms7.2 ms19.534805.7 KB0✓ yes
1,000compas_msgpack_zstd50.6 KB2.818×2.8 ms5.5 ms8.4 ms9.395909.3 KB0✓ yes
10,000json1.4 MB1.0×35.2 ms38.9 ms74.1 ms37.5124.9 MB0✓ yes
10,000json_zip540.0 KB2.641×62.1 ms41.9 ms104.1 ms13.1844.9 MB0✓ yes
10,000compas_pb781.3 KB1.826×33.8 ms51.0 ms84.8 ms15.6922.6 MB0✓ yes
10,000compas_pb_zip252.6 KB5.647×39.9 ms51.2 ms91.1 ms5.053.4 MB0✓ yes
10,000compas_pb_zstd244.1 KB5.842×38.0 ms49.9 ms87.9 ms5.0123.4 MB0✓ yes
10,000compas_msgpack1.0 MB1.378×17.0 ms63.5 ms80.5 ms16.6858.1 MB0✓ yes
10,000compas_msgpack_zstd494.9 KB2.882×31.8 ms70.5 ms102.4 ms7.1849.1 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/results/samples/README.md b/benchmarks/serialization/results/samples/README.md new file mode 100644 index 000000000000..598cf0487ffd --- /dev/null +++ b/benchmarks/serialization/results/samples/README.md @@ -0,0 +1,19 @@ +# Encoded-format samples + +Tiny, fully-inspectable fixtures encoded with the three main (uncompressed) formats, so you +can see the *shape* of each encoding. Regenerate with: + + python -m benchmarks.serialization.samples + +Per subject: + +| file | what it is | +|------|------------| +| `.json` | JSON wire format (text) | +| `.pb` | raw protobuf bytes | +| `.pb.json` | protobuf message deserialized + re-serialized to JSON (readable wire structure) | +| `.msgpack` | raw MessagePack bytes | +| `.msgpack.json` | decoded MessagePack tree as JSON (row-oriented `{dtype, data}`) | + +`*.pb.json` shows the schema'd/columnar layout (flat vertex arrays, CSR faces, attribute +columns); `*.msgpack.json` shows the row-oriented dict tree. diff --git a/benchmarks/serialization/results/samples/boxes.json b/benchmarks/serialization/results/samples/boxes.json new file mode 100644 index 000000000000..595b3ac6a1e7 --- /dev/null +++ b/benchmarks/serialization/results/samples/boxes.json @@ -0,0 +1,54 @@ +[ + { + "data": { + "frame": { + "point": [ + 27.885359691576753, + -94.99784895546661, + -44.99413632617615 + ], + "xaxis": [ + 1.0, + 0.0, + 0.0 + ], + "yaxis": [ + 0.0, + 1.0, + 0.0 + ] + }, + "xsize": 3.008896643339405, + "ysize": 7.628240927476112, + "zsize": 7.0902953868062015 + }, + "dtype": "compas.geometry/Box", + "guid": "e095ce62-ae36-4eb1-b6d3-64b6e4fac7ab" + }, + { + "data": { + "frame": { + "point": [ + 78.43591354096907, + -82.61223347411678, + -15.61563606294591 + ], + "xaxis": [ + 1.0, + 0.0, + 0.0 + ], + "yaxis": [ + 0.0, + 1.0, + 0.0 + ] + }, + "xsize": 1.268174974942633, + "ysize": 2.9677417732324303, + "zsize": 5.548197592930261 + }, + "dtype": "compas.geometry/Box", + "guid": "d7605170-f7c8-41dd-9532-beaec02edd34" + } +] \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/boxes.msgpack b/benchmarks/serialization/results/samples/boxes.msgpack new file mode 100644 index 0000000000000000000000000000000000000000..14022c1e5f6c2d410ee72e4e63b1eb5e8b524902 GIT binary patch literal 461 zcmbQ#yfmexvLJPHa(-?>VzFL&YJP5NNl~S~Q+~ygl*E$6mZcTNnN_K$9XNz6(jDtA zEUkoa<(dPheG}$eS_R?C#FV96wLiNwttc@!wRveler8_Dzs^iissVqp&SiAr1#kKH+cE0-NO=4A0tMO(~0!aUjY22_PH?aa71k9^5^DDJo literal 0 HcmV?d00001 diff --git a/benchmarks/serialization/results/samples/graph.msgpack.json b/benchmarks/serialization/results/samples/graph.msgpack.json new file mode 100644 index 000000000000..1293bbcda4df --- /dev/null +++ b/benchmarks/serialization/results/samples/graph.msgpack.json @@ -0,0 +1,50 @@ +{ + "dtype": "compas.datastructures/Graph", + "data": { + "attributes": {}, + "default_node_attributes": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "default_edge_attributes": {}, + "node": { + "0": { + "x": 0.0, + "y": 0.0, + "z": 0.13942679845788375 + }, + "1": { + "x": 1.0, + "y": 0.0, + "z": -0.47498924477733306 + }, + "2": { + "x": 0.0, + "y": 1.0, + "z": -0.22497068163088074 + }, + "3": { + "x": 1.0, + "y": 1.0, + "z": -0.27678926185117725 + } + }, + "edge": { + "0": { + "1": {}, + "2": {} + }, + "1": { + "3": {} + }, + "2": { + "3": {} + }, + "3": {} + }, + "max_node": 3 + }, + "inheritance": [], + "guid": "ddd89b19-b11f-43a6-9c94-6ffcb91cd76c" +} \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/graph.pb b/benchmarks/serialization/results/samples/graph.pb new file mode 100644 index 0000000000000000000000000000000000000000..dddc811f252443bdfc40ea6dfc6f0a2fb8812659 GIT binary patch literal 255 zcmd=3%EG+=~(mGF*Tx zp@WQ4ObQG@45FEUm|01ci?KpUfdK`4ut(uCe6R;8t3+1@Qv_2EQC6j-Ai{j&;GP=? z?SJ_SdReC3+wbv4%=G=3!#--(5Rfsx6J Qg^`JwS%}p@&s5I<07RQKS^xk5 literal 0 HcmV?d00001 diff --git a/benchmarks/serialization/results/samples/graph.pb.json b/benchmarks/serialization/results/samples/graph.pb.json new file mode 100644 index 000000000000..cd35e3a2ffd7 --- /dev/null +++ b/benchmarks/serialization/results/samples/graph.pb.json @@ -0,0 +1,74 @@ +{ + "data": { + "message": { + "@type": "type.googleapis.com/compas_pb.data.GraphData", + "nodeKeys": [ + { + "intValue": "0" + }, + { + "intValue": "1" + }, + { + "intValue": "2" + }, + { + "intValue": "3" + } + ], + "nodeAttributes": [ + { + "name": "x", + "doubles": [ + 0.0, + 1.0, + 0.0, + 1.0 + ] + }, + { + "name": "y", + "doubles": [ + 0.0, + 0.0, + 1.0, + 1.0 + ] + }, + { + "name": "z", + "doubles": [ + 0.13942679845788375, + -0.47498924477733306, + -0.22497068163088074, + -0.27678926185117725 + ] + } + ], + "defaultNodeAttributes": { + "y": { + "doubleValue": 0.0 + }, + "x": { + "doubleValue": 0.0 + }, + "z": { + "doubleValue": 0.0 + } + }, + "edgeU": [ + 0, + 0, + 1, + 2 + ], + "edgeV": [ + 1, + 2, + 3, + 3 + ] + } + }, + "version": "0.5.0" +} \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/mesh.json b/benchmarks/serialization/results/samples/mesh.json new file mode 100644 index 000000000000..58cb8aa2ca0b --- /dev/null +++ b/benchmarks/serialization/results/samples/mesh.json @@ -0,0 +1,55 @@ +{ + "data": { + "attributes": {}, + "default_edge_attributes": {}, + "default_face_attributes": {}, + "default_vertex_attributes": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "edgedata": {}, + "face": { + "0": [ + 0, + 1, + 3, + 2 + ] + }, + "facedata": { + "0": {} + }, + "max_face": 0, + "max_vertex": 3, + "vertex": { + "0": { + "quality": 0.7364712141640124, + "x": 0.0, + "y": 0.0, + "z": 0.13942679845788375 + }, + "1": { + "quality": 0.6766994874229113, + "x": 1.0, + "y": 0.0, + "z": -0.47498924477733306 + }, + "2": { + "quality": 0.8921795677048454, + "x": 0.0, + "y": 1.0, + "z": -0.22497068163088074 + }, + "3": { + "quality": 0.08693883262941615, + "x": 1.0, + "y": 1.0, + "z": -0.27678926185117725 + } + } + }, + "dtype": "compas.datastructures/Mesh", + "guid": "18409b01-4820-4e7c-ad8f-8ad927880e68", + "inheritance": [] +} \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/mesh.msgpack b/benchmarks/serialization/results/samples/mesh.msgpack new file mode 100644 index 0000000000000000000000000000000000000000..2ef0e812826bb022ee8bd8dd9458cffec7d77eb1 GIT binary patch literal 496 zcmZo!no?3(kh&{5Ker&UST7~9B(b=ps5H5xv?#S$-#4{5V+lyCYgJ-NNl|7}X-R5v z!_Jh{w8YY!lK8UJqLS2#c!X5*!iv)jP_VEP!K{Kax5M1=>Yq$MV!NGyZc z(z4K?1*hru2XE{-c!F7Ed0}Z{PG(8vY5V6Bbwo10)GagwX|n$SaTBVO_TNjh^b+*_ zh0yeLdF#4wg|ikKq1go2Uv+x_nbX(qh`jMYXnNDLM@z3{!a`#-n~*hK-1f@vk>w|Z zrfrV%Cp``5SOW5F<3fWe42;Z7D?l7jU;_mjR)E3>#A#TSn^*x2Y33CmHb@!6>dd^1 z)S}Fi#JuFx2}{yTGgEG=m>3!+nWX_ literal 0 HcmV?d00001 diff --git a/benchmarks/serialization/results/samples/mesh.msgpack.json b/benchmarks/serialization/results/samples/mesh.msgpack.json new file mode 100644 index 000000000000..a08f852005eb --- /dev/null +++ b/benchmarks/serialization/results/samples/mesh.msgpack.json @@ -0,0 +1,55 @@ +{ + "dtype": "compas.datastructures/Mesh", + "data": { + "attributes": {}, + "default_vertex_attributes": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "default_edge_attributes": {}, + "default_face_attributes": {}, + "vertex": { + "0": { + "x": 0.0, + "y": 0.0, + "z": 0.13942679845788375, + "quality": 0.7364712141640124 + }, + "1": { + "x": 1.0, + "y": 0.0, + "z": -0.47498924477733306, + "quality": 0.6766994874229113 + }, + "2": { + "x": 0.0, + "y": 1.0, + "z": -0.22497068163088074, + "quality": 0.8921795677048454 + }, + "3": { + "x": 1.0, + "y": 1.0, + "z": -0.27678926185117725, + "quality": 0.08693883262941615 + } + }, + "face": { + "0": [ + 0, + 1, + 3, + 2 + ] + }, + "facedata": { + "0": {} + }, + "edgedata": {}, + "max_vertex": 3, + "max_face": 0 + }, + "inheritance": [], + "guid": "411c4b44-195f-4723-bb3a-89247c25c31f" +} \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/mesh.pb b/benchmarks/serialization/results/samples/mesh.pb new file mode 100644 index 0000000000000000000000000000000000000000..a46b864c07726a05a75df0c111936d59339c5f86 GIT binary patch literal 261 zcmd=3&B*nGkxRRzvLID2JwHD^CpEDkvsf=VKUW`!3lfXt3zGCw5=#>Gd{c`vT!0Lr z6O2*`3}`@v`NY9JHxAlEgg-!O28Lh0f?k$s_x7VI|6uR&M&!=5(`TUKF!dkoKUqHV zd$sN2ekB$LMrI}>Z7%l0(!`w1l1e3ox-S_bIuoDU&no=3u66lS`w1m_T6=ol*mndx moiyKZo4pqw7h{zWrzXrQ5WfPAUx~y|Vq_6wHPAEFGXMaEUPT)K literal 0 HcmV?d00001 diff --git a/benchmarks/serialization/results/samples/mesh.pb.json b/benchmarks/serialization/results/samples/mesh.pb.json new file mode 100644 index 000000000000..fcc700bbb3ed --- /dev/null +++ b/benchmarks/serialization/results/samples/mesh.pb.json @@ -0,0 +1,53 @@ +{ + "data": { + "message": { + "@type": "type.googleapis.com/compas_pb.data.MeshData", + "vertices": [ + 0.0, + 0.0, + 0.13942679845788375, + 1.0, + 0.0, + -0.47498924477733306, + 0.0, + 1.0, + -0.22497068163088074, + 1.0, + 1.0, + -0.27678926185117725 + ], + "faceVertices": [ + 0, + 1, + 3, + 2 + ], + "vertexAttributeColumns": [ + { + "name": "quality", + "doubles": [ + 0.7364712141640124, + 0.6766994874229113, + 0.8921795677048454, + 0.08693883262941615 + ] + } + ], + "defaultVertexAttributes": { + "y": { + "doubleValue": 0.0 + }, + "x": { + "doubleValue": 0.0 + }, + "z": { + "doubleValue": 0.0 + } + }, + "faceSizes": [ + 4 + ] + } + }, + "version": "0.5.0" +} \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/pointcloud.json b/benchmarks/serialization/results/samples/pointcloud.json new file mode 100644 index 000000000000..66599dcf66ba --- /dev/null +++ b/benchmarks/serialization/results/samples/pointcloud.json @@ -0,0 +1,28 @@ +{ + "data": { + "points": [ + [ + 27.885359691576753, + -94.99784895546661, + -44.99413632617615 + ], + [ + -55.35785237023545, + 47.29424283280247, + 35.33989748458225 + ], + [ + 78.43591354096907, + -82.61223347411678, + -15.61563606294591 + ], + [ + -94.04055611238593, + -56.27240503927933, + 1.0710576206724767 + ] + ] + }, + "dtype": "compas.geometry/Pointcloud", + "guid": "7b356607-1303-43ff-91eb-bbd1fb8673f5" +} \ No newline at end of file diff --git a/benchmarks/serialization/results/samples/pointcloud.msgpack b/benchmarks/serialization/results/samples/pointcloud.msgpack new file mode 100644 index 0000000000000000000000000000000000000000..0e9671440e3181eebe7cb6c1d4208e511ff4c734 GIT binary patch literal 203 zcmV;+05t!DrDSw@aAmq%@PZ*4DQZ*6d4b6;>`E@WYJVJ=W_ zX>N35Y;SdBL}7Gc5@H%)(1ghDrs6w5>xA9G+`m`Am{{=JKYvERih4mC&aF$p2>i#t zsij9i03*V}fvZ74AeQI>=9^PMMmA5?E~iw$h%RZSG&?WAZWgL|n1WZpGkg~--XcuE Sz_-p&4I}YC5(O|WH7+nsx<-Hi literal 0 HcmV?d00001 diff --git a/benchmarks/serialization/results/samples/pointcloud.pb.json b/benchmarks/serialization/results/samples/pointcloud.pb.json new file mode 100644 index 000000000000..0560c793fbb6 --- /dev/null +++ b/benchmarks/serialization/results/samples/pointcloud.pb.json @@ -0,0 +1,22 @@ +{ + "data": { + "message": { + "@type": "type.googleapis.com/compas_pb.data.PointcloudData", + "points": [ + 27.885359691576753, + -94.99784895546661, + -44.99413632617615, + -55.35785237023545, + 47.29424283280247, + 35.33989748458225, + 78.43591354096907, + -82.61223347411678, + -15.61563606294591, + -94.04055611238593, + -56.27240503927933, + 1.0710576206724767 + ] + } + }, + "version": "0.5.0" +} \ No newline at end of file diff --git a/benchmarks/serialization/run.py b/benchmarks/serialization/run.py index 4d37a8c83ab6..931542bb4176 100644 --- a/benchmarks/serialization/run.py +++ b/benchmarks/serialization/run.py @@ -28,15 +28,19 @@ from benchmarks.serialization import formats from benchmarks.serialization import metrics from benchmarks.serialization import report +from benchmarks.serialization import samples HERE = os.path.dirname(__file__) RESULTS_DIR = os.path.join(HERE, "results") -# Per-subject sizes. Mesh sizes are vertex counts; pointcloud sizes are point counts. +# Sizes are element counts (vertices / points / nodes / primitives). DEFAULT_SIZES applies +# to any subject not given explicit sizes in PRESETS. +DEFAULT_SIZES = { + "quick": [1000, 10000], + "full": [1000, 100000, 1000000], +} PRESETS = { "quick": { - "mesh": [1000, 10000], - "mesh_attrs": [1000, 10000], "pointcloud": [10000, 100000], }, "full": { # PRD 10.1 @@ -46,6 +50,10 @@ }, } + +def _sizes_for(preset, subject): + return PRESETS[preset].get(subject, DEFAULT_SIZES[preset]) + CSV_COLUMNS = [ "subject", "size", @@ -91,13 +99,14 @@ def run(subjects, preset, format_names, repeat, seed): raise SystemExit("No matching available formats.") rows = [] - sizes_by_subject = PRESETS[preset] for subject in subjects: factory = fixtures.SUBJECTS[subject] - for size in sizes_by_subject[subject]: - obj = factory(size, seed) - measured = {f.name: metrics.measure(f, obj, repeat=repeat) for f in active_formats} + for size in _sizes_for(preset, subject): + # Build a fresh fixture per format: serializing accesses .guid on some paths (JSON + # forces it), which would mutate a shared object and unfairly change what a later + # format encodes. A pristine object per format keeps each measurement independent. + measured = {f.name: metrics.measure(f, factory(size, seed), repeat=repeat) for f in active_formats} json_size = measured.get("json", {}).get("size_bytes") for fmt in active_formats: @@ -170,6 +179,7 @@ def main(): parser.add_argument("--repeat", type=int, default=5, help="Timed runs per measurement (median reported).") parser.add_argument("--seed", type=int, default=fixtures.DEFAULT_SEED) parser.add_argument("--out", default=os.path.join(RESULTS_DIR, "baseline_quick.csv"), help="CSV output path.") + parser.add_argument("--no-samples", action="store_true", help="Skip writing encoded-format samples.") args = parser.parse_args() rows = run(args.subjects, args.preset, args.formats, args.repeat, args.seed) @@ -179,6 +189,10 @@ def main(): html_out = report.write_html(rows, os.path.splitext(out)[0] + ".html", meta=meta) print("\nWrote {} rows to {}\nWrote report to {}".format(len(rows), out, html_out)) + if not args.no_samples: + sample_files = samples.dump_samples(os.path.join(os.path.dirname(out) or ".", "samples"), seed=args.seed) + print("Wrote {} encoded-format samples to {}/samples/".format(len(sample_files), os.path.dirname(out) or ".")) + if __name__ == "__main__": main() diff --git a/benchmarks/serialization/samples.py b/benchmarks/serialization/samples.py new file mode 100644 index 000000000000..34779b470baa --- /dev/null +++ b/benchmarks/serialization/samples.py @@ -0,0 +1,127 @@ +"""Dump small, human-readable encoded artifacts for the three main (uncompressed) formats. + +The benchmark runs on large fixtures; these are *tiny* fixtures whose whole encoded shape is +inspectable. For each subject we write, into ``results/samples/``: + +* ``.json`` -- the JSON wire format (already text); +* ``.pb`` -- the raw protobuf bytes (binary); +* ``.pb.json`` -- the protobuf message rendered as JSON (``pb_dump_json``), + i.e. the same bytes deserialized and re-serialized to JSON so the wire *structure* is + readable (flat coordinate arrays, CSR faces, attribute columns, ...); +* ``.msgpack`` -- the raw MessagePack bytes (binary); +* ``.msgpack.json`` -- the decoded MessagePack tree as JSON (the row-oriented + ``{dtype, data, ...}`` shape). + +Comparing ``*.pb.json`` (schema'd / columnar) with ``*.msgpack.json`` (row-oriented tree) +shows how the two binary encodings differ in shape. +""" + +import json +import os + +import compas +from benchmarks.serialization import fixtures + +# Small, fully-inspectable fixtures per subject. +SAMPLES = { + "mesh": lambda seed: fixtures.make_mesh(4, with_attributes=True, seed=seed), + "pointcloud": lambda seed: fixtures.make_pointcloud(4, seed=seed), + "graph": lambda seed: fixtures.make_graph(4, seed=seed), + "boxes": lambda seed: fixtures.make_primitives("box", 2, seed=seed), +} + +_README = """# Encoded-format samples + +Tiny, fully-inspectable fixtures encoded with the three main (uncompressed) formats, so you +can see the *shape* of each encoding. Regenerate with: + + python -m benchmarks.serialization.samples + +Per subject: + +| file | what it is | +|------|------------| +| `.json` | JSON wire format (text) | +| `.pb` | raw protobuf bytes | +| `.pb.json` | protobuf message deserialized + re-serialized to JSON (readable wire structure) | +| `.msgpack` | raw MessagePack bytes | +| `.msgpack.json` | decoded MessagePack tree as JSON (row-oriented `{dtype, data}`) | + +`*.pb.json` shows the schema'd/columnar layout (flat vertex arrays, CSR faces, attribute +columns); `*.msgpack.json` shows the row-oriented dict tree. +""" + + +def _write_text(path, text): + with open(path, "w") as f: + f.write(text) + + +def _write_bytes(path, data): + with open(path, "wb") as f: + f.write(data) + + +def dump_samples(out_dir, seed=fixtures.DEFAULT_SEED): + """Write encoded-format samples for each subject into ``out_dir``. + + Binary formats whose optional dependency is missing are skipped (only their readable + JSON renderings are skipped too). + + Returns + ------- + list[str] + The files written. + """ + os.makedirs(out_dir, exist_ok=True) + written = [] + + try: + from compas_pb import pb_dump_bts + from compas_pb import pb_dump_json + except ImportError: + pb_dump_bts = pb_dump_json = None + + try: + import msgspec + + from benchmarks.serialization.formats import _msgpack_enc_hook + except ImportError: + msgspec = None + + for subject, factory in SAMPLES.items(): + # Fresh object per format: JSON dumping forces .guid, which would then appear in a + # subsequent pb/msgpack dump of the same object. Independent objects show each + # format's true shape (e.g. pb omitting auto-generated guids). + json_path = os.path.join(out_dir, subject + ".json") + _write_text(json_path, compas.json_dumps(factory(seed), pretty=True)) + written.append(json_path) + + if pb_dump_bts is not None: + pb_path = os.path.join(out_dir, subject + ".pb") + _write_bytes(pb_path, pb_dump_bts(factory(seed))) + pbjson_path = os.path.join(out_dir, subject + ".pb.json") + _write_text(pbjson_path, pb_dump_json(factory(seed))) + written.extend([pb_path, pbjson_path]) + + if msgspec is not None: + blob = msgspec.msgpack.encode(factory(seed), enc_hook=_msgpack_enc_hook) + mp_path = os.path.join(out_dir, subject + ".msgpack") + _write_bytes(mp_path, blob) + mpjson_path = os.path.join(out_dir, subject + ".msgpack.json") + _write_text(mpjson_path, json.dumps(msgspec.msgpack.decode(blob), indent=2)) + written.extend([mp_path, mpjson_path]) + + _write_text(os.path.join(out_dir, "README.md"), _README) + return written + + +def main(): + here = os.path.dirname(__file__) + out_dir = os.path.join(here, "results", "samples") + written = dump_samples(out_dir) + print("Wrote {} sample files to {}".format(len(written), out_dir)) + + +if __name__ == "__main__": + main() From f951f1e455eba7263eeb8dd899c28c786a7c2b9d Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Fri, 10 Jul 2026 18:54:59 +0200 Subject: [PATCH 07/13] Add compound geometry to the benchmark corpus Adds polylines, polygons, beziers, polyhedrons, and transformations (17 subjects total). The compound types each hold several points, exercising compas_pb's flat repeated-double point arrays; all round-trip losslessly and compas_pb is smallest and faster to load than JSON on them (e.g. polylines@10k: pb 2.4 MB / 269 ms vs json 5.4 MB / 381 ms). Also caps the `full` preset to runnable sizes (mesh 1e6, pointcloud 1e7) so a full run completes in reasonable time/memory; the N1 scaling trend is clear by there. Co-Authored-By: Claude Opus 4.8 --- benchmarks/README.md | 15 +- benchmarks/serialization/fixtures.py | 21 +- .../serialization/results/baseline_quick.csv | 406 ++++++++++-------- .../serialization/results/baseline_quick.html | 2 +- .../serialization/results/samples/boxes.json | 4 +- .../results/samples/boxes.msgpack | Bin 461 -> 461 bytes .../results/samples/boxes.msgpack.json | 4 +- .../serialization/results/samples/graph.json | 2 +- .../results/samples/graph.msgpack | Bin 382 -> 382 bytes .../results/samples/graph.msgpack.json | 2 +- .../serialization/results/samples/graph.pb | Bin 255 -> 255 bytes .../results/samples/graph.pb.json | 6 +- .../serialization/results/samples/mesh.json | 2 +- .../results/samples/mesh.msgpack | Bin 496 -> 496 bytes .../results/samples/mesh.msgpack.json | 2 +- .../serialization/results/samples/mesh.pb | Bin 261 -> 261 bytes .../results/samples/mesh.pb.json | 6 +- .../results/samples/pointcloud.json | 2 +- .../results/samples/pointcloud.msgpack | Bin 203 -> 203 bytes .../results/samples/pointcloud.msgpack.json | 2 +- benchmarks/serialization/run.py | 13 +- 21 files changed, 296 insertions(+), 193 deletions(-) diff --git a/benchmarks/README.md b/benchmarks/README.md index 17718cd36b76..3d315c0cd290 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -24,14 +24,23 @@ For each **subject × size × format**: | `pointcloud` | N float64 points | none¹ | | `graph` | jittered grid, nodes (x,y,z) + edges | per-node coords | | `points`, `vectors`, `lines`, `frames`, `planes`, `boxes`, `spheres`, `circles` | a list of N primitives/shapes | — | +| `polylines`, `polygons`, `beziers`, `polyhedrons` | a list of N compound objects (each holds several points) | — | +| `transformations` | a list of N 4×4 matrices | — | ¹ The COMPAS `Pointcloud` type has no per-point attribute slot, so the "with per-element attributes" case lives on `mesh_attrs`. The primitive/shape subjects are **collections** (a Python `list` of N objects, a common -real-world payload — e.g. a list of frames as robot targets). Fixtures are seeded -([`fixtures.py`](serialization/fixtures.py)) so runs are comparable and reused across every -format; the harness measures a list or a single `Data` object transparently. +real-world payload — e.g. a list of frames as robot targets). The compound subjects +(polylines/polygons/beziers/polyhedrons) each hold several points, so they exercise +compas_pb's flat `repeated double` point arrays. This covers ~15 of compas_pb's ~31 native +geometry types; still uncovered: the conics (Arc/Ellipse/Parabola/Hyperbola), the remaining +shapes (Cylinder/Cone/Capsule/Torus), Quaternion, and the specific transformation subtypes +(Translation/Rotation/Scale/… — which have their own proto messages beyond the base matrix). + +Fixtures are seeded ([`fixtures.py`](serialization/fixtures.py)) so runs are comparable and +reused across every format; the harness measures a list or a single `Data` object +transparently. ## Formats under test diff --git a/benchmarks/serialization/fixtures.py b/benchmarks/serialization/fixtures.py index 6dbf63939b6a..0c5c2b7129e5 100644 --- a/benchmarks/serialization/fixtures.py +++ b/benchmarks/serialization/fixtures.py @@ -19,6 +19,7 @@ from compas.datastructures import Graph from compas.datastructures import Mesh +from compas.geometry import Bezier from compas.geometry import Box from compas.geometry import Circle from compas.geometry import Frame @@ -26,7 +27,11 @@ from compas.geometry import Plane from compas.geometry import Point from compas.geometry import Pointcloud +from compas.geometry import Polygon +from compas.geometry import Polyhedron +from compas.geometry import Polyline from compas.geometry import Sphere +from compas.geometry import Transformation from compas.geometry import Vector DEFAULT_SEED = 42 @@ -146,6 +151,17 @@ def coord(): if kind == "circle": f = Frame(coord(), [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]) return Circle(rng.uniform(1.0, 10.0), frame=f) + # Compound geometry — exercises the flat `repeated double` point arrays in compas_pb. + if kind == "polyline": + return Polyline([coord() for _ in range(8)]) + if kind == "polygon": + return Polygon([coord() for _ in range(6)]) + if kind == "bezier": + return Bezier([coord() for _ in range(4)]) + if kind == "polyhedron": + return Polyhedron([coord() for _ in range(4)], [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]) + if kind == "transformation": + return Transformation.from_frame(Frame(coord(), [1.0, 0.1, 0.0], [0.0, 1.0, 0.1])) raise ValueError("Unknown primitive kind: {}".format(kind)) @@ -170,7 +186,10 @@ def make_primitives(kind, count, seed=DEFAULT_SEED): return [_make_primitive(kind, rng) for _ in range(count)] -_PRIMITIVE_KINDS = ["point", "vector", "line", "frame", "plane", "box", "sphere", "circle"] +_PRIMITIVE_KINDS = [ + "point", "vector", "line", "frame", "plane", "box", "sphere", "circle", + "polyline", "polygon", "bezier", "polyhedron", "transformation", +] # Subject catalogue: label -> factory(size, seed) returning a Data object (or list of them). diff --git a/benchmarks/serialization/results/baseline_quick.csv b/benchmarks/serialization/results/baseline_quick.csv index 7bdf036e0bb5..4eb1b7deda18 100644 --- a/benchmarks/serialization/results/baseline_quick.csv +++ b/benchmarks/serialization/results/baseline_quick.csv @@ -1,169 +1,239 @@ subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -boxes,1000,json,285582,1.0,0.007785,0.001844,0.041193,0.00026,0.048978,36.686,6.933,1727364,True,True,True,0.0,0.0,"compact text, lossless" -boxes,1000,json_zip,89866,3.178,0.011599,0.001823,0.040598,0.000287,0.052197,7.748,2.214,1729869,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -boxes,1000,compas_pb,131015,2.18,0.006713,0.013195,0.045559,0.002559,0.052272,19.516,2.876,1339834,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -boxes,1000,compas_pb_zip,52308,5.46,0.008356,0.000762,0.046564,0.003048,0.05492,6.26,1.123,1472733,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -boxes,1000,compas_pb_zstd,50046,5.706,0.007656,0.000757,0.045315,0.000161,0.05297,6.537,1.104,1470882,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -boxes,1000,compas_msgpack,230003,1.242,0.003446,0.001534,0.046462,0.000112,0.049908,66.753,4.95,2664336,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -boxes,1000,compas_msgpack_zstd,79439,3.595,0.005562,0.00172,0.04691,0.000121,0.052472,14.284,1.693,2896372,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -boxes,10000,json,2855355,1.0,0.083882,0.015251,0.415532,0.011624,0.499414,34.04,6.872,17297673,True,True,True,0.0,0.0,"compact text, lossless" -boxes,10000,json_zip,892072,3.201,0.118557,0.015591,0.431748,0.012822,0.550306,7.524,2.066,17300178,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -boxes,10000,compas_pb,1310015,2.18,0.070668,0.000381,0.482124,0.009117,0.552792,18.538,2.717,13440482,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -boxes,10000,compas_pb_zip,520863,5.482,0.084411,0.000585,0.480021,0.012843,0.564432,6.171,1.085,14751629,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -boxes,10000,compas_pb_zstd,497195,5.743,0.079089,0.001297,0.4818,0.002833,0.560889,6.287,1.032,14750434,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -boxes,10000,compas_msgpack,2300003,1.241,0.035114,0.020122,0.513876,0.020949,0.54899,65.501,4.476,26841536,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -boxes,10000,compas_msgpack_zstd,795391,3.59,0.056956,0.014663,0.500645,0.023084,0.557601,13.965,1.589,29141572,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -circles,1000,json,237208,1.0,0.006579,0.002177,0.038615,0.003538,0.045193,36.056,6.143,1542873,True,True,True,0.0,0.0,"compact text, lossless" -circles,1000,json_zip,68274,3.474,0.0096,0.001692,0.039459,0.000599,0.049059,7.112,1.73,1545762,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -circles,1000,compas_pb,163015,1.455,0.007589,0.00181,0.046472,0.000128,0.054062,21.48,3.508,1358721,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -circles,1000,compas_pb_zip,63498,3.736,0.009726,0.001689,0.046838,0.000123,0.056564,6.529,1.356,1522964,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -circles,1000,compas_pb_zstd,61969,3.828,0.009248,0.00187,0.045993,0.003841,0.055241,6.701,1.347,1521769,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -circles,1000,compas_msgpack,204003,1.163,0.00364,0.001583,0.0478,0.004097,0.05144,56.047,4.268,2531491,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -circles,1000,compas_msgpack_zstd,62162,3.816,0.004772,0.001578,0.045873,0.003392,0.050644,13.027,1.355,2735527,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -circles,10000,json,2372279,1.0,0.066367,0.015783,0.431295,0.018532,0.497662,35.745,5.5,15454648,True,True,True,0.0,0.0,"compact text, lossless" -circles,10000,json_zip,677524,3.501,0.097308,0.016723,0.431064,0.009799,0.528372,6.963,1.572,15457145,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -circles,10000,compas_pb,1630015,1.455,0.078108,0.015657,0.490322,0.005567,0.56843,20.869,3.324,13630497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -circles,10000,compas_pb_zip,631606,3.756,0.101384,0.015583,0.501556,0.000958,0.602941,6.23,1.259,15261684,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -circles,10000,compas_pb_zstd,606407,3.912,0.091088,0.017456,0.502684,0.001467,0.593771,6.657,1.206,15260545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -circles,10000,compas_msgpack,2040003,1.163,0.032588,0.014647,0.499202,0.017768,0.53179,62.6,4.087,25510523,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -circles,10000,compas_msgpack_zstd,608922,3.896,0.048848,0.017091,0.496467,0.008915,0.545315,12.466,1.227,27551655,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -frames,1000,json,295873,1.0,0.007729,0.001793,0.021617,0.00165,0.029346,38.281,13.687,1384395,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"compact text, lossless" -frames,1000,json_zip,109726,2.696,0.014499,0.001534,0.021291,0.000281,0.03579,7.568,5.154,1386900,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"zip-compressed json, size baseline" -frames,1000,compas_pb,141015,2.098,0.005494,0.000189,0.032896,0.003048,0.03839,25.666,4.287,987572,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, double + flat arrays (optimized)" -frames,1000,compas_pb_zip,71467,4.14,0.008474,0.000545,0.026521,0.000141,0.034995,8.434,2.695,1129815,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zip-compressed" -frames,1000,compas_pb_zstd,69763,4.241,0.00686,6.6e-05,0.02596,0.00303,0.03282,10.17,2.687,1128620,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zstandard-compressed" -frames,1000,compas_msgpack,180003,1.644,0.002916,0.001409,0.025497,0.00045,0.028413,61.729,7.06,2083642,False,False,False,4.440892098500626e-16,6.299702658387308e-17,msgpack over the JSON-shape tree (Kumiki-style) -frames,1000,compas_msgpack_zstd,96688,3.06,0.004674,0.00152,0.02526,0.000197,0.029934,20.688,3.828,2261158,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"msgpack, zstandard-compressed" -frames,10000,json,2959373,1.0,0.07323,0.015906,0.22278,0.006959,0.296009,40.412,13.284,13880263,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"compact text, lossless" -frames,10000,json_zip,1090022,2.715,0.134516,0.014495,0.222859,0.008448,0.357376,8.103,4.891,13882928,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"zip-compressed json, size baseline" -frames,10000,compas_pb,1410015,2.099,0.055502,0.000407,0.273539,0.006856,0.329041,25.405,5.155,9920052,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, double + flat arrays (optimized)" -frames,10000,compas_pb_zip,712585,4.153,0.087012,0.001495,0.281689,0.006767,0.368701,8.189,2.53,11331295,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zip-compressed" -frames,10000,compas_pb_zstd,707041,4.186,0.073682,0.000967,0.274891,0.004163,0.348574,9.596,2.572,11330100,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zstandard-compressed" -frames,10000,compas_msgpack,1800003,1.644,0.029463,0.014611,0.291106,0.004979,0.320569,61.094,6.183,21017794,False,False,False,5.551115123125783e-16,6.326276205293956e-17,msgpack over the JSON-shape tree (Kumiki-style) -frames,10000,compas_msgpack_zstd,964081,3.07,0.057417,0.011557,0.283381,0.005289,0.340798,16.791,3.402,22817830,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"msgpack, zstandard-compressed" -graph,1000,json,76719,1.0,0.001761,7.1e-05,0.013687,0.00378,0.015448,43.567,5.605,1938217,True,True,True,0.0,0.0,"compact text, lossless" -graph,1000,json_zip,24330,3.153,0.003479,0.000217,0.012466,0.000252,0.015946,6.993,1.952,1940890,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -graph,1000,compas_pb,37178,2.064,0.004035,0.000133,0.004036,0.000107,0.008071,9.214,9.211,1115572,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -graph,1000,compas_pb_zip,15463,4.961,0.004744,9.3e-05,0.003976,8.9e-05,0.008721,3.259,3.889,1154142,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -graph,1000,compas_pb_zstd,16070,4.774,0.004421,0.000112,0.00402,0.000267,0.008442,3.635,3.997,1152783,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -graph,1000,compas_msgpack,53875,1.424,0.000605,3e-05,0.01465,0.000282,0.015255,89.056,3.677,2544153,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -graph,1000,compas_msgpack_zstd,17746,4.323,0.001218,4.8e-05,0.014688,0.002632,0.015905,14.571,1.208,2598061,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -graph,10000,json,793664,1.0,0.016957,0.000234,0.132289,0.004032,0.149246,46.803,5.999,19036162,True,True,True,0.0,0.0,"compact text, lossless" -graph,10000,json_zip,213388,3.719,0.033907,0.004364,0.137011,0.006698,0.170919,6.293,1.557,19020672,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -graph,10000,compas_pb,368817,2.152,0.039935,0.000462,0.037609,0.004822,0.077544,9.235,9.807,11049444,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -graph,10000,compas_pb_zip,142716,5.561,0.047998,0.001187,0.040069,0.008138,0.088067,2.973,3.562,11419657,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -graph,10000,compas_pb_zstd,185816,4.271,0.043525,0.001102,0.038052,0.004755,0.081577,4.269,4.883,11418294,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -graph,10000,compas_msgpack,564802,1.405,0.008534,0.003907,0.168116,0.005396,0.17665,66.182,3.36,25119679,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -graph,10000,compas_msgpack_zstd,118953,6.672,0.011117,0.003719,0.168573,0.007798,0.179691,10.7,0.706,25684514,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -lines,1000,json,218115,1.0,0.007568,0.001738,0.008024,6.6e-05,0.015591,28.822,27.184,1041873,True,True,True,0.0,0.0,"compact text, lossless" -lines,1000,json_zip,86999,2.507,0.011715,0.001649,0.008508,6.3e-05,0.020224,7.426,10.225,1044906,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -lines,1000,compas_pb,109015,2.001,0.006983,3.3e-05,0.011712,4.3e-05,0.018695,15.612,9.308,722835,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -lines,1000,compas_pb_zip,51798,4.211,0.008763,0.000162,0.012071,0.000186,0.020835,5.911,4.291,833078,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -lines,1000,compas_pb_zstd,50170,4.348,0.007936,9.8e-05,0.011901,0.000103,0.019837,6.322,4.216,831883,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -lines,1000,compas_msgpack,143003,1.525,0.004581,0.001546,0.011647,0.00011,0.016228,31.215,12.278,1663713,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -lines,1000,compas_msgpack_zstd,78551,2.777,0.006112,0.001465,0.011864,0.000568,0.017976,12.852,6.621,1806749,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -lines,10000,json,2181230,1.0,0.081256,0.016077,0.090389,0.00919,0.171645,26.844,24.132,10462004,True,True,True,0.0,0.0,"compact text, lossless" -lines,10000,json_zip,862928,2.528,0.118228,0.018745,0.096666,0.006666,0.214894,7.299,8.927,10464509,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -lines,10000,compas_pb,1090015,2.001,0.073789,0.002596,0.128516,0.005967,0.202305,14.772,8.482,7279619,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -lines,10000,compas_pb_zip,515699,4.23,0.087276,0.000933,0.130785,0.006029,0.218061,5.909,3.943,8370862,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -lines,10000,compas_pb_zstd,498282,4.378,0.078514,0.000494,0.129217,0.004041,0.207731,6.346,3.856,8369667,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -lines,10000,compas_msgpack,1430003,1.525,0.047991,0.015,0.132507,0.001501,0.180498,29.797,10.792,16848977,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -lines,10000,compas_msgpack_zstd,769341,2.835,0.067813,0.012512,0.141122,0.003686,0.208935,11.345,5.452,18277541,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh,1000,json,82154,1.0,0.001502,2.5e-05,0.0036,2.5e-05,0.005101,54.706,22.823,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,json_zip,28050,2.929,0.003545,0.000102,0.003756,6.9e-05,0.007301,7.913,7.469,1614336,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,1000,compas_pb,32913,2.496,0.001739,1.9e-05,0.00328,3.9e-05,0.005019,18.924,10.035,878003,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh,1000,compas_pb_zip,16331,5.031,0.00232,1.6e-05,0.003393,3.7e-05,0.005713,7.038,4.813,912308,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh,1000,compas_pb_zstd,16203,5.07,0.002085,3.3e-05,0.00332,3.8e-05,0.005405,7.77,4.881,910949,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh,1000,compas_msgpack,58668,1.4,0.00043,1.4e-05,0.007532,0.002525,0.007962,136.477,7.789,2063130,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh,1000,compas_msgpack_zstd,25135,3.269,0.001021,1.7e-05,0.007472,3.1e-05,0.008493,24.614,3.364,2121831,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh,10000,json,884888,1.0,0.016384,0.003158,0.044177,0.004078,0.060561,54.008,20.031,16027789,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,json_zip,243866,3.629,0.039129,0.000352,0.043856,0.003776,0.082985,6.232,5.561,16035062,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,10000,compas_pb,328024,2.698,0.017031,0.000139,0.034531,0.005207,0.051562,19.261,9.499,8718587,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh,10000,compas_pb_zip,162262,5.453,0.023818,0.000115,0.034543,0.004322,0.05836,6.813,4.697,9047715,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh,10000,compas_pb_zstd,172651,5.125,0.01989,0.000747,0.03334,0.003896,0.05323,8.68,5.179,9046644,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh,10000,compas_msgpack,621054,1.425,0.004903,0.000495,0.088312,0.002331,0.093215,126.672,7.033,20579024,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh,10000,compas_msgpack_zstd,203525,4.348,0.008411,0.000364,0.087099,0.001089,0.095511,24.196,2.337,21200111,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh_attrs,1000,json,112098,1.0,0.001986,6.7e-05,0.003914,2.4e-05,0.0059,56.457,28.639,1666431,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,json_zip,38109,2.942,0.004442,0.000115,0.003943,2.9e-05,0.008385,8.58,9.665,1669096,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,1000,compas_pb,41120,2.726,0.002045,0.000159,0.003583,0.003079,0.005629,20.104,11.475,967891,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh_attrs,1000,compas_pb_zip,24312,4.611,0.0026,0.00012,0.003513,3e-06,0.006113,9.351,6.92,1010407,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh_attrs,1000,compas_pb_zstd,24277,4.617,0.002336,2.6e-05,0.003387,5.1e-05,0.005723,10.392,7.169,1009044,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh_attrs,1000,compas_msgpack,76076,1.474,0.00044,1.8e-05,0.008014,0.003104,0.008454,172.704,9.493,2087922,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh_attrs,1000,compas_msgpack_zstd,33792,3.317,0.001301,3.3e-05,0.008099,2.8e-05,0.0094,25.98,4.172,2164031,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh_attrs,10000,json,1177508,1.0,0.019797,0.003064,0.048608,0.004987,0.068405,59.479,24.224,16560465,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,json_zip,347070,3.393,0.051306,0.002635,0.051502,0.001903,0.102808,6.765,6.739,16563738,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,10000,compas_pb,408041,2.886,0.019976,0.002875,0.035178,0.00382,0.055153,20.427,11.599,9597267,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh_attrs,10000,compas_pb_zip,238533,4.936,0.028754,0.002849,0.041106,0.003493,0.06986,8.296,5.803,10007512,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh_attrs,10000,compas_pb_zstd,238887,4.929,0.02227,0.000264,0.034494,0.004362,0.056764,10.727,6.925,10005341,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh_attrs,10000,compas_msgpack,791054,1.489,0.004515,0.000147,0.092655,0.002137,0.09717,175.222,8.538,20822216,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh_attrs,10000,compas_msgpack_zstd,282066,4.175,0.01016,0.000342,0.089878,0.007055,0.100039,27.761,3.138,21611119,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -planes,1000,json,225141,1.0,0.005406,0.001551,0.008302,0.002691,0.013708,41.646,27.118,1048924,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"compact text, lossless" -planes,1000,json_zip,87456,2.574,0.010019,0.001533,0.008831,5.8e-05,0.01885,8.729,9.903,1051621,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"zip-compressed json, size baseline" -planes,1000,compas_pb,110015,2.046,0.004704,8.5e-05,0.013028,0.002934,0.017733,23.387,8.444,722652,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, double + flat arrays (optimized)" -planes,1000,compas_pb_zip,52297,4.305,0.006098,0.000107,0.012638,8e-05,0.018735,8.577,4.138,833895,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zip-compressed" -planes,1000,compas_pb_zstd,50611,4.448,0.005746,0.000207,0.013177,0.000112,0.018923,8.808,3.841,832700,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zstandard-compressed" -planes,1000,compas_msgpack,147003,1.532,0.00254,0.001398,0.012447,0.00013,0.014986,57.881,11.811,1664479,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,msgpack over the JSON-shape tree (Kumiki-style) -planes,1000,compas_msgpack_zstd,79365,2.837,0.004019,0.001495,0.012334,0.00289,0.016353,19.749,6.435,1811515,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"msgpack, zstandard-compressed" -planes,10000,json,2251968,1.0,0.054689,0.014844,0.09411,0.00626,0.1488,41.177,23.929,10532543,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"compact text, lossless" -planes,10000,json_zip,866566,2.599,0.10046,0.015386,0.100463,0.005787,0.200923,8.626,8.626,10535528,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"zip-compressed json, size baseline" -planes,10000,compas_pb,1100015,2.047,0.045995,0.000161,0.130369,0.005152,0.176363,23.916,8.438,7279204,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, double + flat arrays (optimized)" -planes,10000,compas_pb_zip,520659,4.325,0.062105,0.000212,0.140755,0.005426,0.20286,8.383,3.699,8380447,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zip-compressed" -planes,10000,compas_pb_zstd,508937,4.425,0.056183,0.00043,0.134108,0.004695,0.190291,9.059,3.795,8379252,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zstandard-compressed" -planes,10000,compas_msgpack,1470003,1.532,0.024178,0.014464,0.133392,0.001057,0.15757,60.8,11.02,16858631,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,msgpack over the JSON-shape tree (Kumiki-style) -planes,10000,compas_msgpack_zstd,780156,2.887,0.039609,0.01471,0.141388,0.006416,0.180997,19.697,5.518,18327187,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"msgpack, zstandard-compressed" -pointcloud,10000,json,580633,1.0,0.013331,0.003144,0.013293,0.003293,0.026624,43.555,43.68,4261534,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,json_zip,280724,2.068,0.033267,9.5e-05,0.014547,0.002679,0.047814,8.439,19.297,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,10000,compas_pb,240074,2.419,0.0031,4.4e-05,0.01054,0.003274,0.013639,77.451,22.778,3599350,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -pointcloud,10000,compas_pb_zip,228795,2.538,0.009161,4.4e-05,0.011221,0.003335,0.020382,24.976,20.39,3840652,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -pointcloud,10000,compas_pb_zstd,227771,2.549,0.003329,2.9e-05,0.011655,0.002563,0.014983,68.43,19.543,3839561,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -pointcloud,10000,compas_msgpack,280093,2.073,0.003666,9.8e-05,0.026973,0.003116,0.03064,76.399,10.384,4570603,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -pointcloud,10000,compas_msgpack_zstd,250823,2.315,0.004733,6.9e-05,0.032582,0.000968,0.037315,52.994,7.698,4850729,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -pointcloud,100000,json,5804860,1.0,0.150705,0.001237,0.188525,0.001163,0.33923,38.518,30.791,42602609,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,json_zip,2792760,2.079,0.354503,0.005964,0.209641,0.018254,0.564144,7.878,13.322,42599930,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,100000,compas_pb,2400078,2.419,0.032003,0.000291,0.158647,0.010433,0.190649,74.996,15.128,35996478,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -pointcloud,100000,compas_pb_zip,2286030,2.539,0.094398,0.000759,0.176587,0.003583,0.270985,24.217,12.946,38397656,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -pointcloud,100000,compas_pb_zstd,2276982,2.549,0.034991,0.000747,0.170809,0.003774,0.2058,65.074,13.331,38396589,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -pointcloud,100000,compas_msgpack,2800095,2.073,0.049033,0.000188,0.353375,0.0107,0.402408,57.107,7.924,45598744,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -pointcloud,100000,compas_msgpack_zstd,2457514,2.362,0.082358,0.001446,0.371287,0.003603,0.453645,29.839,6.619,48398819,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -points,1000,json,145071,1.0,0.003946,0.00134,0.003612,0.000143,0.007557,36.768,40.168,512822,True,True,True,0.0,0.0,"compact text, lossless" -points,1000,json_zip,55949,2.593,0.006128,0.001679,0.00408,0.000252,0.010207,9.131,13.714,515327,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -points,1000,compas_pb,79015,1.836,0.003564,0.000193,0.005187,0.000245,0.008751,22.169,15.233,266342,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -points,1000,compas_pb_zip,26095,5.559,0.004203,0.000124,0.00512,0.000128,0.009323,6.209,5.097,346581,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -points,1000,compas_pb_zstd,24960,5.812,0.003914,0.000241,0.004912,0.000171,0.008827,6.377,5.081,345390,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -points,1000,compas_msgpack,105003,1.382,0.001722,0.001465,0.005296,0.000104,0.007018,60.973,19.826,824071,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -points,1000,compas_msgpack_zstd,51853,2.798,0.002833,0.0014,0.005195,0.00014,0.008029,18.301,9.981,931099,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -points,10000,json,1450530,1.0,0.03542,0.014215,0.037479,0.00484,0.072899,40.952,38.703,5170601,True,True,True,0.0,0.0,"compact text, lossless" -points,10000,json_zip,552776,2.624,0.059725,0.0159,0.039387,0.004675,0.099112,9.255,14.034,5173098,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -points,10000,compas_pb,790015,1.836,0.032246,0.000275,0.048519,0.003197,0.080765,24.5,16.283,2718662,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -points,10000,compas_pb_zip,258617,5.609,0.042655,0.001369,0.05043,0.000308,0.093085,6.063,5.128,3510433,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -points,10000,compas_pb_zstd,247395,5.863,0.036958,0.000165,0.048617,0.003018,0.085575,6.694,5.089,3508710,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -points,10000,compas_msgpack,1050003,1.381,0.016752,0.013633,0.061366,0.004546,0.078118,62.678,17.11,8455711,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -points,10000,compas_msgpack_zstd,511645,2.835,0.028419,0.013873,0.062845,0.00201,0.091264,18.004,8.141,9505747,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -spheres,1000,json,237252,1.0,0.007789,0.001879,0.038637,0.00021,0.046426,30.46,6.14,1630917,True,True,True,0.0,0.0,"compact text, lossless" -spheres,1000,json_zip,68288,3.474,0.009534,0.001652,0.039141,0.000165,0.048675,7.162,1.745,1633422,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -spheres,1000,compas_pb,115015,2.063,0.007303,0.000491,0.047104,0.00417,0.054408,15.748,2.442,1291821,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -spheres,1000,compas_pb_zip,35118,6.756,0.007768,0.000113,0.046415,0.00131,0.054182,4.521,0.757,1408292,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -spheres,1000,compas_pb_zstd,33203,7.145,0.007374,7.7e-05,0.045207,0.000251,0.052581,4.503,0.734,1406869,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -spheres,1000,compas_msgpack,204003,1.163,0.003768,0.00128,0.046801,0.000704,0.050569,54.14,4.359,2619323,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -spheres,1000,compas_msgpack_zstd,62218,3.813,0.004893,0.001743,0.045986,0.000181,0.050879,12.715,1.353,2823359,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -spheres,10000,json,2372345,1.0,0.068659,0.016699,0.411094,0.007129,0.479753,34.553,5.771,16334546,True,True,True,0.0,0.0,"compact text, lossless" -spheres,10000,json_zip,677372,3.502,0.100829,0.023523,0.412016,0.004245,0.512846,6.718,1.644,16337051,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -spheres,10000,compas_pb,1150015,2.063,0.067687,0.001746,0.477364,0.012154,0.54505,16.99,2.409,12960429,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -spheres,10000,compas_pb_zip,348595,6.805,0.081801,0.000708,0.47126,0.00317,0.553061,4.262,0.74,14111672,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -spheres,10000,compas_pb_zstd,334774,7.086,0.07759,0.000986,0.479162,0.004213,0.556753,4.315,0.699,14110477,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -spheres,10000,compas_msgpack,2040003,1.163,0.032219,0.015286,0.493436,0.017911,0.525655,63.317,4.134,26391451,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -spheres,10000,compas_msgpack_zstd,608979,3.896,0.050654,0.016311,0.516215,0.017076,0.56687,12.022,1.18,28431935,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -vectors,1000,json,146071,1.0,0.003896,0.001581,0.003872,0.000172,0.007768,37.493,37.727,513823,True,True,True,0.0,0.0,"compact text, lossless" -vectors,1000,json_zip,55991,2.609,0.00605,0.001626,0.004528,0.002722,0.010578,9.255,12.365,516328,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -vectors,1000,compas_pb,80015,1.826,0.003286,5e-05,0.005089,5.9e-05,0.008376,24.347,15.722,266345,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -vectors,1000,compas_pb_zip,26096,5.597,0.003884,0.000148,0.005128,3.5e-05,0.009012,6.719,5.088,347588,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -vectors,1000,compas_pb_zstd,24962,5.852,0.00377,7.8e-05,0.005034,1.9e-05,0.008804,6.621,4.959,346393,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -vectors,1000,compas_msgpack,106003,1.378,0.001812,0.001398,0.005427,0.000134,0.007238,58.509,19.534,825072,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -vectors,1000,compas_msgpack_zstd,51841,2.818,0.002835,0.001433,0.005518,0.000105,0.008353,18.288,9.395,931108,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -vectors,10000,json,1460530,1.0,0.035207,0.015179,0.038935,0.005051,0.074142,41.484,37.512,5180650,True,True,True,0.0,0.0,"compact text, lossless" -vectors,10000,json_zip,552978,2.641,0.062124,0.015071,0.041944,0.00591,0.104068,8.901,13.184,5183107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -vectors,10000,compas_pb,800015,1.826,0.033781,0.00066,0.050982,0.002816,0.084763,23.682,15.692,2718665,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -vectors,10000,compas_pb_zip,258630,5.647,0.039896,0.000318,0.051209,0.000264,0.091105,6.483,5.05,3519908,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -vectors,10000,compas_pb_zstd,249995,5.842,0.037993,0.000743,0.049877,0.003142,0.08787,6.58,5.012,3518713,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -vectors,10000,compas_msgpack,1060003,1.378,0.016991,0.013967,0.063531,0.006412,0.080522,62.386,16.685,8466176,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -vectors,10000,compas_msgpack_zstd,506817,2.882,0.031833,0.01724,0.070547,0.005589,0.10238,15.921,7.184,9526212,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +beziers,1000,json,333223,1.0,0.008053,0.001805,0.009788,0.000363,0.017841,41.379,34.043,1769015,True,True,True,0.0,0.0,"compact text, lossless" +beziers,1000,json_zip,145252,2.294,0.016243,0.001289,0.010026,0.00014,0.026269,8.942,14.488,1771520,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +beziers,1000,compas_pb,155015,2.15,0.004889,0.016199,0.010363,0.000114,0.015253,31.705,14.958,1334485,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +beziers,1000,compas_pb_zip,93529,3.563,0.006915,0.000153,0.010848,0.002825,0.017763,13.526,8.622,1490728,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +beziers,1000,compas_pb_zstd,92304,3.61,0.005847,0.000791,0.010976,0.002813,0.016823,15.786,8.41,1489533,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +beziers,1000,compas_msgpack,199003,1.674,0.002952,0.001526,0.016482,0.00314,0.019434,67.412,12.074,2458467,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +beziers,1000,compas_msgpack_zstd,128826,2.587,0.005413,0.001538,0.016909,0.003196,0.022322,23.801,7.619,2657039,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +beziers,10000,json,3332149,1.0,0.084562,0.014893,0.115758,0.011194,0.200321,39.405,28.785,17768533,True,True,True,0.0,0.0,"compact text, lossless" +beziers,10000,json_zip,1443213,2.309,0.162178,0.014786,0.126444,0.001504,0.288622,8.899,11.414,17771030,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +beziers,10000,compas_pb,1550015,2.15,0.047374,0.000309,0.122872,0.001941,0.170246,32.719,12.615,13435021,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +beziers,10000,compas_pb_zip,933499,3.57,0.073697,0.001654,0.126436,0.011806,0.200133,12.667,7.383,14986264,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +beziers,10000,compas_pb_zstd,926258,3.597,0.0632,0.000191,0.124579,0.005258,0.187779,14.656,7.435,14985069,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +beziers,10000,compas_msgpack,1990003,1.674,0.030441,0.013809,0.210213,0.009641,0.240653,65.373,9.467,24790043,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +beziers,10000,compas_msgpack_zstd,1291176,2.581,0.048862,0.01491,0.200492,0.004164,0.249354,26.425,6.44,26780079,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +boxes,1000,json,285582,1.0,0.007315,0.001619,0.038544,3e-05,0.045859,39.04,7.409,1727364,True,True,True,0.0,0.0,"compact text, lossless" +boxes,1000,json_zip,89855,3.178,0.011275,0.002171,0.03897,0.000142,0.050245,7.969,2.306,1730085,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +boxes,1000,compas_pb,131015,2.18,0.006448,0.000149,0.044059,2.1e-05,0.050507,20.319,2.974,1339834,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +boxes,1000,compas_pb_zip,52308,5.46,0.008753,0.00021,0.044547,0.000133,0.0533,5.976,1.174,1472077,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,1000,compas_pb_zstd,50046,5.706,0.007797,0.00087,0.04526,0.003518,0.053057,6.419,1.106,1470882,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +boxes,1000,compas_msgpack,230003,1.242,0.003319,0.001527,0.045709,0.002939,0.049029,69.295,5.032,2664800,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +boxes,1000,compas_msgpack_zstd,79451,3.594,0.005382,0.001523,0.045574,0.003515,0.050956,14.763,1.743,2894372,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +boxes,10000,json,2855355,1.0,0.074427,0.016362,0.41365,0.002075,0.488077,38.365,6.903,17297673,True,True,True,0.0,0.0,"compact text, lossless" +boxes,10000,json_zip,891963,3.201,0.119041,0.017291,0.449364,0.012573,0.568405,7.493,1.985,17300170,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +boxes,10000,compas_pb,1310015,2.18,0.06711,0.000933,0.476184,0.00628,0.543294,19.521,2.751,13440506,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +boxes,10000,compas_pb_zip,520863,5.482,0.08087,0.000902,0.479365,0.006597,0.560234,6.441,1.087,14751629,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,10000,compas_pb_zstd,497195,5.743,0.080377,0.002135,0.471277,0.01144,0.551654,6.186,1.055,14750530,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +boxes,10000,compas_msgpack,2300003,1.241,0.034169,0.015722,0.506779,0.011271,0.540948,67.313,4.538,26841536,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +boxes,10000,compas_msgpack_zstd,795487,3.589,0.061757,0.024524,0.496986,0.009737,0.558743,12.881,1.601,29141572,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +circles,1000,json,237208,1.0,0.006606,0.002315,0.038653,0.003894,0.045259,35.907,6.137,1542873,True,True,True,0.0,0.0,"compact text, lossless" +circles,1000,json_zip,68256,3.475,0.009217,0.001763,0.038832,0.000104,0.048049,7.405,1.758,1545762,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +circles,1000,compas_pb,163015,1.455,0.007568,0.001971,0.045387,8e-05,0.052955,21.541,3.592,1358721,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +circles,1000,compas_pb_zip,63511,3.735,0.009595,0.001767,0.045852,5.9e-05,0.055447,6.619,1.385,1522960,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +circles,1000,compas_pb_zstd,62011,3.825,0.009048,0.001676,0.045625,0.002803,0.054673,6.853,1.359,1521769,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +circles,1000,compas_msgpack,204003,1.163,0.003179,0.001488,0.044433,0.0029,0.047612,64.173,4.591,2531491,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +circles,1000,compas_msgpack_zstd,62185,3.815,0.004723,0.001585,0.044486,0.003104,0.049209,13.168,1.398,2735527,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +circles,10000,json,2372279,1.0,0.066669,0.016652,0.408942,0.00181,0.47561,35.583,5.801,15454648,True,True,True,0.0,0.0,"compact text, lossless" +circles,10000,json_zip,677434,3.502,0.09812,0.015015,0.412371,0.003712,0.510491,6.904,1.643,15457153,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +circles,10000,compas_pb,1630015,1.455,0.076792,0.017032,0.482421,0.003404,0.559214,21.226,3.379,13630497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +circles,10000,compas_pb_zip,631718,3.755,0.102003,0.017806,0.493721,0.002114,0.595724,6.193,1.28,15261680,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +circles,10000,compas_pb_zstd,606552,3.911,0.090033,0.016918,0.488508,0.003028,0.578541,6.737,1.242,15260545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +circles,10000,compas_msgpack,2040003,1.163,0.033959,0.016078,0.492754,0.008114,0.526713,60.072,4.14,25510523,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +circles,10000,compas_msgpack_zstd,608987,3.895,0.046051,0.015785,0.48713,0.007126,0.533181,13.224,1.25,27551655,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +frames,1000,json,295873,1.0,0.007069,0.001622,0.019677,3.7e-05,0.026745,41.857,15.037,1384395,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"compact text, lossless" +frames,1000,json_zip,109781,2.695,0.0137,0.001559,0.02134,5.2e-05,0.03504,8.013,5.144,1386900,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"zip-compressed json, size baseline" +frames,1000,compas_pb,141015,2.098,0.00551,5.9e-05,0.025163,0.002682,0.030673,25.593,5.604,987572,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, double + flat arrays (optimized)" +frames,1000,compas_pb_zip,71467,4.14,0.007925,9e-05,0.025378,0.000133,0.033303,9.018,2.816,1129815,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zip-compressed" +frames,1000,compas_pb_zstd,69763,4.241,0.006724,0.000124,0.026123,0.002876,0.032846,10.376,2.671,1128620,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zstandard-compressed" +frames,1000,compas_msgpack,180003,1.644,0.002888,0.001394,0.024767,5.2e-05,0.027655,62.324,7.268,2083642,False,False,False,4.440892098500626e-16,6.299702658387308e-17,msgpack over the JSON-shape tree (Kumiki-style) +frames,1000,compas_msgpack_zstd,96626,3.062,0.004769,0.001488,0.025018,0.000209,0.029787,20.261,3.862,2261158,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"msgpack, zstandard-compressed" +frames,10000,json,2959373,1.0,0.079435,0.016291,0.215612,0.003767,0.295047,37.255,13.725,13880263,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"compact text, lossless" +frames,10000,json_zip,1090210,2.714,0.138246,0.016397,0.218419,0.002101,0.356666,7.886,4.991,13882936,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"zip-compressed json, size baseline" +frames,10000,compas_pb,1410015,2.099,0.059869,0.000532,0.265558,0.002933,0.325427,23.552,5.31,9920052,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, double + flat arrays (optimized)" +frames,10000,compas_pb_zip,712585,4.153,0.085895,0.001122,0.272389,0.000624,0.358284,8.296,2.616,11331295,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zip-compressed" +frames,10000,compas_pb_zstd,707041,4.186,0.067435,0.002162,0.269815,0.006557,0.33725,10.485,2.62,11330100,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zstandard-compressed" +frames,10000,compas_msgpack,1800003,1.644,0.031532,0.014811,0.290208,0.003166,0.32174,57.086,6.202,21017794,False,False,False,5.551115123125783e-16,6.326276205293956e-17,msgpack over the JSON-shape tree (Kumiki-style) +frames,10000,compas_msgpack_zstd,964070,3.07,0.053088,0.015512,0.287917,0.005105,0.341005,18.16,3.348,22817830,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"msgpack, zstandard-compressed" +graph,1000,json,76719,1.0,0.001786,7.7e-05,0.012365,3.5e-05,0.014151,42.962,6.204,1938217,True,True,True,0.0,0.0,"compact text, lossless" +graph,1000,json_zip,24330,3.153,0.003589,5.8e-05,0.012371,7.1e-05,0.01596,6.779,1.967,1940890,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +graph,1000,compas_pb,37178,2.064,0.004272,3.6e-05,0.003996,6.5e-05,0.008268,8.702,9.305,1115572,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +graph,1000,compas_pb_zip,15463,4.961,0.004811,6.9e-05,0.003851,3.1e-05,0.008662,3.214,4.015,1154146,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +graph,1000,compas_pb_zstd,16070,4.774,0.004275,1.7e-05,0.003752,6.6e-05,0.008027,3.759,4.283,1152783,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +graph,1000,compas_msgpack,53875,1.424,0.000596,1.4e-05,0.01428,0.00026,0.014876,90.451,3.773,2544153,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +graph,1000,compas_msgpack_zstd,17744,4.324,0.00122,2.6e-05,0.01462,0.00266,0.01584,14.545,1.214,2598061,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +graph,10000,json,793664,1.0,0.016456,0.000247,0.134153,0.004838,0.15061,48.228,5.916,19036162,True,True,True,0.0,0.0,"compact text, lossless" +graph,10000,json_zip,213387,3.719,0.034444,0.003612,0.125682,0.004374,0.160126,6.195,1.698,19020680,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +graph,10000,compas_pb,368817,2.152,0.040617,0.00036,0.037491,0.006643,0.078108,9.08,9.838,11049444,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +graph,10000,compas_pb_zip,142716,5.561,0.04711,0.000144,0.038196,0.00464,0.085306,3.029,3.736,11419653,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +graph,10000,compas_pb_zstd,185816,4.271,0.041276,0.000305,0.037137,0.004461,0.078413,4.502,5.004,11418294,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +graph,10000,compas_msgpack,564802,1.405,0.00665,0.003021,0.170606,0.009322,0.177255,84.937,3.311,25119679,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +graph,10000,compas_msgpack_zstd,118955,6.672,0.011698,0.003943,0.179458,0.0085,0.191156,10.169,0.663,25684514,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +lines,1000,json,218115,1.0,0.0079,0.001705,0.008041,0.000205,0.01594,27.611,27.126,1041873,True,True,True,0.0,0.0,"compact text, lossless" +lines,1000,json_zip,87005,2.507,0.012707,0.001701,0.008436,4.5e-05,0.021143,6.847,10.314,1044906,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +lines,1000,compas_pb,109015,2.001,0.006863,5.3e-05,0.011539,3.7e-05,0.018402,15.885,9.447,722835,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +lines,1000,compas_pb_zip,51798,4.211,0.008927,0.00068,0.012131,0.000327,0.021058,5.802,4.27,833078,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +lines,1000,compas_pb_zstd,50170,4.348,0.007774,9e-05,0.011629,3.9e-05,0.019403,6.454,4.314,831883,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +lines,1000,compas_msgpack,143003,1.525,0.004703,0.001558,0.011746,0.000194,0.016449,30.404,12.175,1663713,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +lines,1000,compas_msgpack_zstd,78603,2.775,0.006365,0.001657,0.011943,0.000225,0.018308,12.349,6.582,1806749,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +lines,10000,json,2181230,1.0,0.079982,0.016048,0.09071,0.005426,0.170692,27.271,24.046,10462004,True,True,True,0.0,0.0,"compact text, lossless" +lines,10000,json_zip,862939,2.528,0.122976,0.018102,0.098295,0.007233,0.221271,7.017,8.779,10464509,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +lines,10000,compas_pb,1090015,2.001,0.07221,0.000431,0.127358,0.005378,0.199568,15.095,8.559,7279619,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +lines,10000,compas_pb_zip,515699,4.23,0.086365,0.000856,0.124603,0.004662,0.210968,5.971,4.139,8370862,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +lines,10000,compas_pb_zstd,498282,4.378,0.078998,0.00135,0.127704,0.006328,0.206702,6.308,3.902,8369667,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +lines,10000,compas_msgpack,1430003,1.525,0.046774,0.014975,0.136317,0.00262,0.183091,30.573,10.49,16848977,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +lines,10000,compas_msgpack_zstd,769503,2.835,0.061887,0.015096,0.136837,0.002043,0.198725,12.434,5.623,18277541,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh,1000,json,82154,1.0,0.001784,0.00035,0.003741,6e-05,0.005525,46.058,21.96,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,json_zip,28054,2.928,0.003763,0.000152,0.003807,0.000121,0.00757,7.456,7.369,1614336,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,1000,compas_pb,32913,2.496,0.001869,4.3e-05,0.003364,9.1e-05,0.005233,17.613,9.784,878003,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,1000,compas_pb_zip,16331,5.031,0.002347,5.5e-05,0.003472,8.4e-05,0.005819,6.959,4.704,912312,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,1000,compas_pb_zstd,16203,5.07,0.002041,3.7e-05,0.003661,0.000144,0.005702,7.94,4.426,910949,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh,1000,compas_msgpack,58668,1.4,0.000449,2.8e-05,0.00776,0.002811,0.00821,130.567,7.56,2063130,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh,1000,compas_msgpack_zstd,25135,3.269,0.001042,2.1e-05,0.007727,0.000128,0.008769,24.119,3.253,2121831,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh,10000,json,884888,1.0,0.016405,0.003335,0.045678,0.002961,0.062083,53.939,19.372,16027789,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,json_zip,243867,3.629,0.040479,0.00069,0.043813,0.003245,0.084293,6.024,5.566,16035054,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,10000,compas_pb,328024,2.698,0.0178,0.000198,0.035438,0.004142,0.053238,18.428,9.256,8718587,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,10000,compas_pb_zip,162262,5.453,0.023866,0.000211,0.036516,0.004905,0.060383,6.799,4.444,9047715,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,10000,compas_pb_zstd,172651,5.125,0.020953,0.000407,0.035712,0.003777,0.056666,8.24,4.835,9046644,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh,10000,compas_msgpack,621054,1.425,0.004525,0.000396,0.090281,0.001787,0.094806,137.255,6.879,20579024,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh,10000,compas_msgpack_zstd,203523,4.348,0.007804,0.000347,0.085776,0.001181,0.09358,26.079,2.373,21200111,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh_attrs,1000,json,112098,1.0,0.00183,4.2e-05,0.003787,6.7e-05,0.005617,61.249,29.6,1666431,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,json_zip,38109,2.942,0.004363,7.1e-05,0.004169,0.000125,0.008532,8.735,9.141,1669096,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,1000,compas_pb,41120,2.726,0.001966,2.9e-05,0.003449,0.00247,0.005415,20.92,11.922,967891,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,1000,compas_pb_zip,24312,4.611,0.002733,6.1e-05,0.003545,5.1e-05,0.006278,8.895,6.858,1010407,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,1000,compas_pb_zstd,24277,4.617,0.002297,3.6e-05,0.003441,5.5e-05,0.005738,10.57,7.055,1009044,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh_attrs,1000,compas_msgpack,76076,1.474,0.000429,1.4e-05,0.008044,0.002594,0.008473,177.247,9.457,2087922,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh_attrs,1000,compas_msgpack_zstd,33791,3.317,0.001258,3.5e-05,0.008046,9.5e-05,0.009305,26.857,4.2,2164031,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh_attrs,10000,json,1177508,1.0,0.019554,0.002963,0.046098,0.004152,0.065652,60.22,25.544,16560465,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,json_zip,347076,3.393,0.047292,6.2e-05,0.046679,0.001569,0.093971,7.339,7.435,16563730,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,10000,compas_pb,408041,2.886,0.019859,0.002949,0.034536,0.004195,0.054395,20.547,11.815,9597267,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,10000,compas_pb_zip,238533,4.936,0.029333,0.000462,0.040921,0.00339,0.070254,8.132,5.829,10007512,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,10000,compas_pb_zstd,238887,4.929,0.022272,0.000145,0.035083,0.004233,0.057355,10.726,6.809,10005341,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh_attrs,10000,compas_msgpack,791054,1.489,0.004344,6e-05,0.089806,0.001004,0.09415,182.111,8.808,20822216,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh_attrs,10000,compas_msgpack_zstd,282067,4.175,0.011222,9.5e-05,0.092232,0.005109,0.103454,25.136,3.058,21611119,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +planes,1000,json,225141,1.0,0.005475,0.001531,0.008438,0.002697,0.013913,41.124,26.681,1048924,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"compact text, lossless" +planes,1000,json_zip,87412,2.576,0.00987,0.001539,0.008702,1.5e-05,0.018572,8.856,10.045,1051621,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"zip-compressed json, size baseline" +planes,1000,compas_pb,110015,2.046,0.00479,6.6e-05,0.012433,0.0027,0.017223,22.967,8.849,722652,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, double + flat arrays (optimized)" +planes,1000,compas_pb_zip,52297,4.305,0.006128,5.3e-05,0.012491,8.3e-05,0.01862,8.534,4.187,833895,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zip-compressed" +planes,1000,compas_pb_zstd,50611,4.448,0.00546,1.1e-05,0.012431,6.9e-05,0.017892,9.269,4.071,832700,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zstandard-compressed" +planes,1000,compas_msgpack,147003,1.532,0.002354,0.001437,0.011839,6.3e-05,0.014194,62.44,12.416,1664479,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,msgpack over the JSON-shape tree (Kumiki-style) +planes,1000,compas_msgpack_zstd,79332,2.838,0.003944,0.001443,0.011977,0.002898,0.015921,20.114,6.624,1811515,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"msgpack, zstandard-compressed" +planes,10000,json,2251968,1.0,0.054412,0.015752,0.096471,0.007461,0.150884,41.387,23.343,10532543,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"compact text, lossless" +planes,10000,json_zip,866765,2.598,0.098359,0.015385,0.098315,0.002762,0.196674,8.812,8.816,10535528,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"zip-compressed json, size baseline" +planes,10000,compas_pb,1100015,2.047,0.04917,0.000274,0.135197,0.005433,0.184367,22.372,8.136,7279204,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, double + flat arrays (optimized)" +planes,10000,compas_pb_zip,520659,4.325,0.062706,8.6e-05,0.130507,0.004233,0.193213,8.303,3.99,8380447,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zip-compressed" +planes,10000,compas_pb_zstd,508937,4.425,0.054706,0.000455,0.130808,0.004392,0.185514,9.303,3.891,8379252,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zstandard-compressed" +planes,10000,compas_msgpack,1470003,1.532,0.023675,0.014511,0.131108,0.001496,0.154784,62.09,11.212,16858631,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,msgpack over the JSON-shape tree (Kumiki-style) +planes,10000,compas_msgpack_zstd,780053,2.887,0.037661,0.014412,0.13805,0.001155,0.17571,20.713,5.651,18327187,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"msgpack, zstandard-compressed" +pointcloud,10000,json,580633,1.0,0.013356,0.002828,0.013528,0.002871,0.026884,43.473,42.921,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,json_zip,280727,2.068,0.035566,0.001337,0.014714,0.00263,0.05028,7.893,19.079,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,10000,compas_pb,240074,2.419,0.003076,2.5e-05,0.010566,0.002776,0.013642,78.041,22.722,3599350,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,10000,compas_pb_zip,228795,2.538,0.009117,7.6e-05,0.01107,0.003169,0.020187,25.096,20.668,3840652,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,10000,compas_pb_zstd,227771,2.549,0.003334,2.6e-05,0.010746,0.002511,0.01408,68.323,21.195,3839561,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +pointcloud,10000,compas_msgpack,280093,2.073,0.003568,6.2e-05,0.027097,0.002654,0.030665,78.493,10.337,4570603,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +pointcloud,10000,compas_msgpack_zstd,250823,2.315,0.004644,0.000399,0.027967,0.003391,0.032611,54.015,8.968,4852841,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +pointcloud,100000,json,5804860,1.0,0.150311,0.002649,0.191948,0.001367,0.342259,38.619,30.242,42602609,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,json_zip,2792760,2.079,0.352092,0.005212,0.187703,0.013331,0.539795,7.932,14.879,42599922,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,100000,compas_pb,2400078,2.419,0.0306,0.000112,0.151125,0.000633,0.181725,78.434,15.881,35996478,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,100000,compas_pb_zip,2286030,2.539,0.093928,0.000882,0.160119,0.002561,0.254047,24.338,14.277,38397656,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,100000,compas_pb_zstd,2276982,2.549,0.03412,0.000811,0.157367,0.002441,0.191487,66.735,14.469,38396589,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +pointcloud,100000,compas_msgpack,2800095,2.073,0.049369,0.005413,0.331642,0.01213,0.381011,56.718,8.443,45598691,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +pointcloud,100000,compas_msgpack_zstd,2457514,2.362,0.080575,0.000884,0.353567,0.007032,0.434142,30.5,6.951,48398819,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +points,1000,json,145071,1.0,0.003509,0.001437,0.003686,8.9e-05,0.007195,41.347,39.354,512438,True,True,True,0.0,0.0,"compact text, lossless" +points,1000,json_zip,55990,2.591,0.005809,0.001406,0.003825,8.9e-05,0.009633,9.639,14.64,514943,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +points,1000,compas_pb,79015,1.836,0.003233,3.7e-05,0.004766,4e-05,0.007999,24.438,16.58,266342,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +points,1000,compas_pb_zip,26095,5.559,0.00397,3.4e-05,0.004904,2.4e-05,0.008874,6.573,5.321,346581,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +points,1000,compas_pb_zstd,24960,5.812,0.003665,3.1e-05,0.004784,1.9e-05,0.008449,6.811,5.217,345390,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +points,1000,compas_msgpack,105003,1.382,0.001667,0.001429,0.005161,0.00011,0.006829,62.977,20.344,824071,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +points,1000,compas_msgpack_zstd,51865,2.797,0.002828,0.001367,0.005322,0.002501,0.008151,18.338,9.745,929571,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +points,10000,json,1450530,1.0,0.034953,0.014082,0.036641,0.004078,0.071595,41.499,39.587,5170601,True,True,True,0.0,0.0,"compact text, lossless" +points,10000,json_zip,552705,2.624,0.064172,0.011874,0.038685,0.004966,0.102857,8.613,14.287,5173106,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +points,10000,compas_pb,790015,1.836,0.03197,0.000242,0.047933,0.003068,0.079903,24.711,16.482,2718662,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +points,10000,compas_pb_zip,258617,5.609,0.040594,0.000693,0.050191,0.000683,0.090786,6.371,5.153,3510433,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +points,10000,compas_pb_zstd,247395,5.863,0.035943,0.000322,0.048346,0.002784,0.084289,6.883,5.117,3508710,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +points,10000,compas_msgpack,1050003,1.381,0.016601,0.013621,0.061133,0.002561,0.077734,63.25,17.176,8455711,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +points,10000,compas_msgpack_zstd,511417,2.836,0.026948,0.013793,0.060286,0.004142,0.087233,18.978,8.483,9505747,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polygons,1000,json,450157,1.0,0.010854,0.002061,0.019155,0.002953,0.030009,41.474,23.501,2558352,True,True,True,0.0,0.0,"compact text, lossless" +polygons,1000,json_zip,202709,2.221,0.022638,0.001594,0.018982,0.002912,0.04162,8.954,10.679,2560857,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polygons,1000,compas_pb,204015,2.206,0.005327,5.4e-05,0.018321,6.4e-05,0.023649,38.297,11.135,2007118,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polygons,1000,compas_pb_zip,139427,3.229,0.00888,0.000124,0.019401,0.000488,0.028281,15.701,7.187,2212465,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polygons,1000,compas_pb_zstd,138167,3.258,0.006613,0.00014,0.019799,0.003533,0.026412,20.893,6.978,2211166,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polygons,1000,compas_msgpack,256003,1.758,0.00392,0.001408,0.028547,0.004206,0.032467,65.315,8.968,3309412,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polygons,1000,compas_msgpack_zstd,178179,2.526,0.006667,0.001446,0.028091,0.0032,0.034758,26.727,6.343,3563984,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polygons,10000,json,4502991,1.0,0.112961,0.01392,0.210527,0.003006,0.323488,39.863,21.389,25659610,True,True,True,0.0,0.0,"compact text, lossless" +polygons,10000,json_zip,2017012,2.233,0.228178,0.015428,0.218753,0.011442,0.446931,8.84,9.22,25662107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polygons,10000,compas_pb,2040015,2.207,0.054759,0.000294,0.210319,0.005139,0.265078,37.254,9.7,20155542,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polygons,10000,compas_pb_zip,1392267,3.234,0.091232,0.000744,0.212406,0.008573,0.303638,15.261,6.555,22196785,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polygons,10000,compas_pb_zstd,1377765,3.268,0.068493,0.001219,0.21167,0.010215,0.280164,20.115,6.509,22195590,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polygons,10000,compas_msgpack,2560003,1.759,0.037196,0.014469,0.337435,0.005699,0.374631,68.825,7.587,33279052,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polygons,10000,compas_msgpack_zstd,1793895,2.51,0.062264,0.014073,0.339987,0.005353,0.402251,28.811,5.276,35840672,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polyhedrons,1000,json,381223,1.0,0.007652,0.001535,0.006331,0.000196,0.013982,49.823,60.218,1840795,True,True,True,0.0,0.0,"compact text, lossless" +polyhedrons,1000,json_zip,146926,2.595,0.015272,0.001548,0.007007,0.003028,0.022279,9.621,20.968,1843300,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polyhedrons,1000,compas_pb,185015,2.06,0.007758,9.7e-05,0.008143,0.003202,0.015901,23.849,22.72,1294035,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polyhedrons,1000,compas_pb_zip,93696,4.069,0.00975,6.9e-05,0.008669,0.003007,0.01842,9.609,10.808,1481086,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polyhedrons,1000,compas_pb_zstd,92462,4.123,0.008748,8.5e-05,0.008235,0.000104,0.016982,10.57,11.228,1479187,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polyhedrons,1000,compas_msgpack,228003,1.672,0.001667,0.001374,0.020084,0.002944,0.02175,136.798,11.353,2893503,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polyhedrons,1000,compas_msgpack_zstd,129213,2.95,0.003757,0.001371,0.020298,0.002851,0.024055,34.39,6.366,3121539,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polyhedrons,10000,json,3812149,1.0,0.07813,0.013673,0.089729,0.004626,0.16786,48.792,42.485,18488497,True,True,True,0.0,0.0,"compact text, lossless" +polyhedrons,10000,json_zip,1461008,2.609,0.151673,0.014539,0.104054,0.013647,0.255726,9.633,14.041,18491002,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polyhedrons,10000,compas_pb,1850015,2.061,0.078912,0.001643,0.106419,0.015543,0.185331,23.444,17.384,13034459,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polyhedrons,10000,compas_pb_zip,934857,4.078,0.100031,0.000225,0.110484,0.011559,0.210515,9.346,8.461,14885950,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polyhedrons,10000,compas_pb_zstd,929108,4.103,0.08776,0.000521,0.107464,0.012687,0.195224,10.587,8.646,14884507,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polyhedrons,10000,compas_msgpack,2280003,1.672,0.017072,0.01343,0.263547,0.002455,0.280619,133.554,8.651,29149551,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polyhedrons,10000,compas_msgpack_zstd,1293846,2.946,0.035365,0.018552,0.267279,0.018314,0.302644,36.586,4.841,31428635,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polylines,1000,json,567347,1.0,0.013518,0.001676,0.015163,0.000485,0.028681,41.97,37.416,3091421,True,True,True,0.0,0.0,"compact text, lossless" +polylines,1000,json_zip,259494,2.186,0.029262,0.001644,0.015873,0.003194,0.045135,8.868,16.348,3094638,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polylines,1000,compas_pb,253015,2.242,0.005903,9.1e-05,0.014154,0.000106,0.020058,42.859,17.875,2422895,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polylines,1000,compas_pb_zip,185252,3.063,0.010635,5.7e-05,0.01472,0.003012,0.025355,17.419,12.585,2677942,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polylines,1000,compas_pb_zstd,183803,3.087,0.007594,5.2e-05,0.014956,0.002434,0.02255,24.203,12.29,2675943,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polylines,1000,compas_msgpack,313003,1.813,0.004412,0.001549,0.027059,0.003478,0.031471,70.947,11.568,3900909,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polylines,1000,compas_msgpack_zstd,234107,2.423,0.006519,0.001552,0.027803,0.003176,0.034322,35.912,8.42,4213481,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polylines,10000,json,5673763,1.0,0.139841,0.01487,0.180078,0.010341,0.319918,40.573,31.507,30990429,True,True,True,0.0,0.0,"compact text, lossless" +polylines,10000,json_zip,2584623,2.195,0.302751,0.011527,0.190907,0.013831,0.493658,8.537,13.539,30992926,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polylines,10000,compas_pb,2530017,2.243,0.06205,0.000499,0.168124,0.013537,0.230174,40.774,15.049,24315487,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polylines,10000,compas_pb_zip,1850649,3.066,0.109176,0.000522,0.180016,0.015054,0.289192,16.951,10.28,26846672,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polylines,10000,compas_pb_zstd,1833306,3.095,0.077302,0.000578,0.171753,0.010044,0.249055,23.716,10.674,26845537,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polylines,10000,compas_msgpack,3130003,1.813,0.044383,0.01987,0.340488,0.020104,0.384871,70.523,9.193,39209909,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polylines,10000,compas_msgpack_zstd,2289784,2.478,0.07409,0.014597,0.351148,0.009403,0.425238,30.906,6.521,42340521,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +spheres,1000,json,237252,1.0,0.006457,0.00171,0.037608,0.000167,0.044064,36.746,6.309,1630917,True,True,True,0.0,0.0,"compact text, lossless" +spheres,1000,json_zip,68346,3.471,0.009261,0.00224,0.038384,0.000128,0.047646,7.38,1.781,1633422,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +spheres,1000,compas_pb,115015,2.063,0.006343,0.000152,0.045034,0.003502,0.051378,18.132,2.554,1291821,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +spheres,1000,compas_pb_zip,35118,6.756,0.007651,0.000683,0.044358,8e-05,0.052008,4.59,0.792,1408348,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +spheres,1000,compas_pb_zstd,33203,7.145,0.007232,7e-05,0.044133,0.000682,0.051366,4.591,0.752,1406869,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +spheres,1000,compas_msgpack,204003,1.163,0.003132,0.001571,0.044098,5.1e-05,0.04723,65.13,4.626,2619323,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +spheres,1000,compas_msgpack_zstd,62222,3.813,0.004717,0.001562,0.044309,0.000104,0.049026,13.19,1.404,2823359,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +spheres,10000,json,2372345,1.0,0.06542,0.016586,0.396201,0.001356,0.461621,36.263,5.988,16334546,True,True,True,0.0,0.0,"compact text, lossless" +spheres,10000,json_zip,677402,3.502,0.095117,0.021832,0.401387,0.004925,0.496504,7.122,1.688,16337051,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +spheres,10000,compas_pb,1150015,2.063,0.063511,0.000197,0.453103,0.010945,0.516613,18.107,2.538,12960429,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +spheres,10000,compas_pb_zip,348595,6.805,0.075044,0.001015,0.459728,0.004858,0.534772,4.645,0.758,14111616,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +spheres,10000,compas_pb_zstd,334774,7.086,0.072479,0.001112,0.458323,0.011566,0.530802,4.619,0.73,14110477,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +spheres,10000,compas_msgpack,2040003,1.163,0.03361,0.01705,0.476355,0.008071,0.509965,60.696,4.283,26391899,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +spheres,10000,compas_msgpack_zstd,609097,3.895,0.046622,0.016041,0.476749,0.013505,0.523371,13.065,1.278,28431935,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +transformations,1000,json,351071,1.0,0.006607,0.001718,0.005302,0.003144,0.011908,53.14,66.22,1426647,True,True,True,0.0,0.0,"compact text, lossless" +transformations,1000,json_zip,61305,5.727,0.009436,0.001413,0.005143,7.5e-05,0.014579,6.497,11.921,1429144,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +transformations,1000,compas_pb,195015,1.8,0.005503,7.2e-05,0.00696,8.1e-05,0.012463,35.44,28.019,973949,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +transformations,1000,compas_pb_zip,27972,12.551,0.00664,7e-05,0.006796,0.00012,0.013436,4.213,4.116,1170192,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +transformations,1000,compas_pb_zstd,24128,14.55,0.006794,7.7e-05,0.006674,8.6e-05,0.013468,3.551,3.615,1168997,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +transformations,1000,compas_msgpack,243003,1.445,0.001478,0.00144,0.014471,0.002808,0.015949,164.418,16.792,2137547,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +transformations,1000,compas_msgpack_zstd,52909,6.635,0.003239,0.001445,0.0133,0.002938,0.016539,16.336,3.978,2380583,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +transformations,10000,json,3510530,1.0,0.06795,0.013563,0.065274,0.009046,0.133224,51.664,53.781,14346826,True,True,True,0.0,0.0,"compact text, lossless" +transformations,10000,json_zip,608715,5.767,0.091882,0.014353,0.06447,0.006701,0.156351,6.625,9.442,14348995,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +transformations,10000,compas_pb,1950015,1.8,0.061022,0.005379,0.095173,0.012267,0.156194,31.956,20.489,9834437,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +transformations,10000,compas_pb_zip,276160,12.712,0.065256,0.000119,0.079394,0.006441,0.144651,4.232,3.478,11785680,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +transformations,10000,compas_pb_zstd,250340,14.023,0.070112,0.001604,0.077305,0.005821,0.147417,3.571,3.238,11784485,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +transformations,10000,compas_msgpack,2430003,1.445,0.014985,0.013363,0.169863,0.013262,0.184848,162.161,14.306,21587227,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +transformations,10000,compas_msgpack_zstd,515176,6.814,0.03113,0.014119,0.180689,0.015662,0.211819,16.549,2.851,24017263,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +vectors,1000,json,146071,1.0,0.00354,0.001471,0.003796,0.000116,0.007336,41.267,38.482,513823,True,True,True,0.0,0.0,"compact text, lossless" +vectors,1000,json_zip,55910,2.613,0.005814,0.001538,0.004024,0.000117,0.009838,9.616,13.894,516328,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +vectors,1000,compas_pb,80015,1.826,0.003267,1.4e-05,0.00491,1.5e-05,0.008177,24.492,16.296,266345,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +vectors,1000,compas_pb_zip,26096,5.597,0.003855,6.7e-05,0.005061,2.1e-05,0.008916,6.77,5.156,347588,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +vectors,1000,compas_pb_zstd,24962,5.852,0.003753,9.7e-05,0.005068,6.8e-05,0.00882,6.652,4.926,346393,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +vectors,1000,compas_msgpack,106003,1.378,0.001673,0.001409,0.005621,0.000268,0.007294,63.355,18.858,825072,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +vectors,1000,compas_msgpack_zstd,51808,2.819,0.002904,0.001582,0.005933,0.000263,0.008837,17.838,8.733,931108,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +vectors,10000,json,1460530,1.0,0.035592,0.015402,0.039156,0.005009,0.074748,41.035,37.3,5180650,True,True,True,0.0,0.0,"compact text, lossless" +vectors,10000,json_zip,552940,2.641,0.06153,0.014493,0.042894,0.004846,0.104424,8.987,12.891,5183107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +vectors,10000,compas_pb,800015,1.826,0.034889,0.00032,0.052195,0.002942,0.087084,22.93,15.327,2718665,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +vectors,10000,compas_pb_zip,258630,5.647,0.039753,0.000354,0.051404,0.000822,0.091157,6.506,5.031,3519908,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +vectors,10000,compas_pb_zstd,249995,5.842,0.036802,0.001163,0.050101,0.003043,0.086903,6.793,4.99,3518713,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +vectors,10000,compas_msgpack,1060003,1.378,0.016814,0.014722,0.055728,0.004335,0.072542,63.043,19.021,8467704,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +vectors,10000,compas_msgpack_zstd,507001,2.881,0.026296,0.014114,0.059855,0.003598,0.086151,19.281,8.47,9527740,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" diff --git a/benchmarks/serialization/results/baseline_quick.html b/benchmarks/serialization/results/baseline_quick.html index 0407be9315d9..e8479a5a4f0b 100644 --- a/benchmarks/serialization/results/baseline_quick.html +++ b/benchmarks/serialization/results/baseline_quick.html @@ -87,7 +87,7 @@ .segmented button.active { background: var(--surface); color: var(--text-primary); font-weight: 600; box-shadow: 0 1px 2px rgba(0,0,0,0.10); } .tile .rng { font-size: 11px; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; } -

COMPAS serialization benchmark

generated 2026-07-10 12:35 · preset quick · repeat 3 · seed 42 · compas 2.15.0-6fec8b70

Show formats
json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, double + flat arrays (optimized)compas_pb_zip · protobuf binary, zip-compressedcompas_pb_zstd · protobuf binary, zstandard-compressedcompas_msgpack · msgpack over the JSON-shape tree (Kumiki-style)compas_msgpack_zstd · msgpack, zstandard-compressed

boxes

Round-trip time
1,000 elements
json
49.0 ms
json_zip
52.2 ms
compas_pb
52.3 ms
compas_pb_zip
54.9 ms
compas_pb_zstd
53.0 ms
compas_msgpack
49.9 ms
compas_msgpack_zstd
52.5 ms
10,000 elements
json
499.4 ms
json_zip
550.3 ms
compas_pb
552.8 ms
compas_pb_zip
564.4 ms
compas_pb_zstd
560.9 ms
compas_msgpack
549.0 ms
compas_msgpack_zstd
557.6 ms
Wire size
1,000 elements
json
278.9 KB
json_zip
87.8 KB
compas_pb
127.9 KB
compas_pb_zip
51.1 KB
compas_pb_zstd
48.9 KB
compas_msgpack
224.6 KB
compas_msgpack_zstd
77.6 KB
10,000 elements
json
2.7 MB
json_zip
871.2 KB
compas_pb
1.2 MB
compas_pb_zip
508.7 KB
compas_pb_zstd
485.5 KB
compas_msgpack
2.2 MB
compas_msgpack_zstd
776.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json278.9 KB1.0×7.8 ms41.2 ms49.0 ms6.9331.6 MB0✓ yes
1,000json_zip87.8 KB3.178×11.6 ms40.6 ms52.2 ms2.2141.6 MB0✓ yes
1,000compas_pb127.9 KB2.18×6.7 ms45.6 ms52.3 ms2.8761.3 MB0✓ yes
1,000compas_pb_zip51.1 KB5.46×8.4 ms46.6 ms54.9 ms1.1231.4 MB0✓ yes
1,000compas_pb_zstd48.9 KB5.706×7.7 ms45.3 ms53.0 ms1.1041.4 MB0✓ yes
1,000compas_msgpack224.6 KB1.242×3.4 ms46.5 ms49.9 ms4.952.5 MB0✓ yes
1,000compas_msgpack_zstd77.6 KB3.595×5.6 ms46.9 ms52.5 ms1.6932.8 MB0✓ yes
10,000json2.7 MB1.0×83.9 ms415.5 ms499.4 ms6.87216.5 MB0✓ yes
10,000json_zip871.2 KB3.201×118.6 ms431.7 ms550.3 ms2.06616.5 MB0✓ yes
10,000compas_pb1.2 MB2.18×70.7 ms482.1 ms552.8 ms2.71712.8 MB0✓ yes
10,000compas_pb_zip508.7 KB5.482×84.4 ms480.0 ms564.4 ms1.08514.1 MB0✓ yes
10,000compas_pb_zstd485.5 KB5.743×79.1 ms481.8 ms560.9 ms1.03214.1 MB0✓ yes
10,000compas_msgpack2.2 MB1.241×35.1 ms513.9 ms549.0 ms4.47625.6 MB0✓ yes
10,000compas_msgpack_zstd776.7 KB3.59×57.0 ms500.6 ms557.6 ms1.58927.8 MB0✓ yes

circles

Round-trip time
1,000 elements
json
45.2 ms
json_zip
49.1 ms
compas_pb
54.1 ms
compas_pb_zip
56.6 ms
compas_pb_zstd
55.2 ms
compas_msgpack
51.4 ms
compas_msgpack_zstd
50.6 ms
10,000 elements
json
497.7 ms
json_zip
528.4 ms
compas_pb
568.4 ms
compas_pb_zip
602.9 ms
compas_pb_zstd
593.8 ms
compas_msgpack
531.8 ms
compas_msgpack_zstd
545.3 ms
Wire size
1,000 elements
json
231.6 KB
json_zip
66.7 KB
compas_pb
159.2 KB
compas_pb_zip
62.0 KB
compas_pb_zstd
60.5 KB
compas_msgpack
199.2 KB
compas_msgpack_zstd
60.7 KB
10,000 elements
json
2.3 MB
json_zip
661.6 KB
compas_pb
1.6 MB
compas_pb_zip
616.8 KB
compas_pb_zstd
592.2 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
594.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json231.6 KB1.0×6.6 ms38.6 ms45.2 ms6.1431.5 MB0✓ yes
1,000json_zip66.7 KB3.474×9.6 ms39.5 ms49.1 ms1.731.5 MB0✓ yes
1,000compas_pb159.2 KB1.455×7.6 ms46.5 ms54.1 ms3.5081.3 MB0✓ yes
1,000compas_pb_zip62.0 KB3.736×9.7 ms46.8 ms56.6 ms1.3561.5 MB0✓ yes
1,000compas_pb_zstd60.5 KB3.828×9.2 ms46.0 ms55.2 ms1.3471.5 MB0✓ yes
1,000compas_msgpack199.2 KB1.163×3.6 ms47.8 ms51.4 ms4.2682.4 MB0✓ yes
1,000compas_msgpack_zstd60.7 KB3.816×4.8 ms45.9 ms50.6 ms1.3552.6 MB0✓ yes
10,000json2.3 MB1.0×66.4 ms431.3 ms497.7 ms5.514.7 MB0✓ yes
10,000json_zip661.6 KB3.501×97.3 ms431.1 ms528.4 ms1.57214.7 MB0✓ yes
10,000compas_pb1.6 MB1.455×78.1 ms490.3 ms568.4 ms3.32413.0 MB0✓ yes
10,000compas_pb_zip616.8 KB3.756×101.4 ms501.6 ms602.9 ms1.25914.6 MB0✓ yes
10,000compas_pb_zstd592.2 KB3.912×91.1 ms502.7 ms593.8 ms1.20614.6 MB0✓ yes
10,000compas_msgpack1.9 MB1.163×32.6 ms499.2 ms531.8 ms4.08724.3 MB0✓ yes
10,000compas_msgpack_zstd594.7 KB3.896×48.8 ms496.5 ms545.3 ms1.22726.3 MB0✓ yes

frames

Round-trip time
1,000 elements
json
29.3 ms
json_zip
35.8 ms
compas_pb
38.4 ms
compas_pb_zip
35.0 ms
compas_pb_zstd
32.8 ms
compas_msgpack
28.4 ms
compas_msgpack_zstd
29.9 ms
10,000 elements
json
296.0 ms
json_zip
357.4 ms
compas_pb
329.0 ms
compas_pb_zip
368.7 ms
compas_pb_zstd
348.6 ms
compas_msgpack
320.6 ms
compas_msgpack_zstd
340.8 ms
Wire size
1,000 elements
json
288.9 KB
json_zip
107.2 KB
compas_pb
137.7 KB
compas_pb_zip
69.8 KB
compas_pb_zstd
68.1 KB
compas_msgpack
175.8 KB
compas_msgpack_zstd
94.4 KB
10,000 elements
json
2.8 MB
json_zip
1.0 MB
compas_pb
1.3 MB
compas_pb_zip
695.9 KB
compas_pb_zstd
690.5 KB
compas_msgpack
1.7 MB
compas_msgpack_zstd
941.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json288.9 KB1.0×7.7 ms21.6 ms29.3 ms13.6871.3 MB4.4e-16✗ no
1,000json_zip107.2 KB2.696×14.5 ms21.3 ms35.8 ms5.1541.3 MB4.4e-16✗ no
1,000compas_pb137.7 KB2.098×5.5 ms32.9 ms38.4 ms4.287964.4 KB4.4e-16✗ no
1,000compas_pb_zip69.8 KB4.14×8.5 ms26.5 ms35.0 ms2.6951.1 MB4.4e-16✗ no
1,000compas_pb_zstd68.1 KB4.241×6.9 ms26.0 ms32.8 ms2.6871.1 MB4.4e-16✗ no
1,000compas_msgpack175.8 KB1.644×2.9 ms25.5 ms28.4 ms7.062.0 MB4.4e-16✗ no
1,000compas_msgpack_zstd94.4 KB3.06×4.7 ms25.3 ms29.9 ms3.8282.2 MB4.4e-16✗ no
10,000json2.8 MB1.0×73.2 ms222.8 ms296.0 ms13.28413.2 MB5.6e-16✗ no
10,000json_zip1.0 MB2.715×134.5 ms222.9 ms357.4 ms4.89113.2 MB5.6e-16✗ no
10,000compas_pb1.3 MB2.099×55.5 ms273.5 ms329.0 ms5.1559.5 MB5.6e-16✗ no
10,000compas_pb_zip695.9 KB4.153×87.0 ms281.7 ms368.7 ms2.5310.8 MB5.6e-16✗ no
10,000compas_pb_zstd690.5 KB4.186×73.7 ms274.9 ms348.6 ms2.57210.8 MB5.6e-16✗ no
10,000compas_msgpack1.7 MB1.644×29.5 ms291.1 ms320.6 ms6.18320.0 MB5.6e-16✗ no
10,000compas_msgpack_zstd941.5 KB3.07×57.4 ms283.4 ms340.8 ms3.40221.8 MB5.6e-16✗ no

graph

Round-trip time
1,000 elements
json
15.4 ms
json_zip
15.9 ms
compas_pb
8.1 ms
compas_pb_zip
8.7 ms
compas_pb_zstd
8.4 ms
compas_msgpack
15.3 ms
compas_msgpack_zstd
15.9 ms
10,000 elements
json
149.2 ms
json_zip
170.9 ms
compas_pb
77.5 ms
compas_pb_zip
88.1 ms
compas_pb_zstd
81.6 ms
compas_msgpack
176.7 ms
compas_msgpack_zstd
179.7 ms
Wire size
1,000 elements
json
74.9 KB
json_zip
23.8 KB
compas_pb
36.3 KB
compas_pb_zip
15.1 KB
compas_pb_zstd
15.7 KB
compas_msgpack
52.6 KB
compas_msgpack_zstd
17.3 KB
10,000 elements
json
775.1 KB
json_zip
208.4 KB
compas_pb
360.2 KB
compas_pb_zip
139.4 KB
compas_pb_zstd
181.5 KB
compas_msgpack
551.6 KB
compas_msgpack_zstd
116.2 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json74.9 KB1.0×1.8 ms13.7 ms15.4 ms5.6051.8 MB0✓ yes
1,000json_zip23.8 KB3.153×3.5 ms12.5 ms15.9 ms1.9521.9 MB0✓ yes
1,000compas_pb36.3 KB2.064×4.0 ms4.0 ms8.1 ms9.2111.1 MB0✓ yes
1,000compas_pb_zip15.1 KB4.961×4.7 ms4.0 ms8.7 ms3.8891.1 MB0✓ yes
1,000compas_pb_zstd15.7 KB4.774×4.4 ms4.0 ms8.4 ms3.9971.1 MB0✓ yes
1,000compas_msgpack52.6 KB1.424×0.6 ms14.7 ms15.3 ms3.6772.4 MB0✓ yes
1,000compas_msgpack_zstd17.3 KB4.323×1.2 ms14.7 ms15.9 ms1.2082.5 MB0✓ yes
10,000json775.1 KB1.0×17.0 ms132.3 ms149.2 ms5.99918.2 MB0✓ yes
10,000json_zip208.4 KB3.719×33.9 ms137.0 ms170.9 ms1.55718.1 MB0✓ yes
10,000compas_pb360.2 KB2.152×39.9 ms37.6 ms77.5 ms9.80710.5 MB0✓ yes
10,000compas_pb_zip139.4 KB5.561×48.0 ms40.1 ms88.1 ms3.56210.9 MB0✓ yes
10,000compas_pb_zstd181.5 KB4.271×43.5 ms38.1 ms81.6 ms4.88310.9 MB0✓ yes
10,000compas_msgpack551.6 KB1.405×8.5 ms168.1 ms176.7 ms3.3624.0 MB0✓ yes
10,000compas_msgpack_zstd116.2 KB6.672×11.1 ms168.6 ms179.7 ms0.70624.5 MB0✓ yes

lines

Round-trip time
1,000 elements
json
15.6 ms
json_zip
20.2 ms
compas_pb
18.7 ms
compas_pb_zip
20.8 ms
compas_pb_zstd
19.8 ms
compas_msgpack
16.2 ms
compas_msgpack_zstd
18.0 ms
10,000 elements
json
171.6 ms
json_zip
214.9 ms
compas_pb
202.3 ms
compas_pb_zip
218.1 ms
compas_pb_zstd
207.7 ms
compas_msgpack
180.5 ms
compas_msgpack_zstd
208.9 ms
Wire size
1,000 elements
json
213.0 KB
json_zip
85.0 KB
compas_pb
106.5 KB
compas_pb_zip
50.6 KB
compas_pb_zstd
49.0 KB
compas_msgpack
139.7 KB
compas_msgpack_zstd
76.7 KB
10,000 elements
json
2.1 MB
json_zip
842.7 KB
compas_pb
1.0 MB
compas_pb_zip
503.6 KB
compas_pb_zstd
486.6 KB
compas_msgpack
1.4 MB
compas_msgpack_zstd
751.3 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json213.0 KB1.0×7.6 ms8.0 ms15.6 ms27.1841017.5 KB0✓ yes
1,000json_zip85.0 KB2.507×11.7 ms8.5 ms20.2 ms10.2251020.4 KB0✓ yes
1,000compas_pb106.5 KB2.001×7.0 ms11.7 ms18.7 ms9.308705.9 KB0✓ yes
1,000compas_pb_zip50.6 KB4.211×8.8 ms12.1 ms20.8 ms4.291813.6 KB0✓ yes
1,000compas_pb_zstd49.0 KB4.348×7.9 ms11.9 ms19.8 ms4.216812.4 KB0✓ yes
1,000compas_msgpack139.7 KB1.525×4.6 ms11.6 ms16.2 ms12.2781.6 MB0✓ yes
1,000compas_msgpack_zstd76.7 KB2.777×6.1 ms11.9 ms18.0 ms6.6211.7 MB0✓ yes
10,000json2.1 MB1.0×81.3 ms90.4 ms171.6 ms24.13210.0 MB0✓ yes
10,000json_zip842.7 KB2.528×118.2 ms96.7 ms214.9 ms8.92710.0 MB0✓ yes
10,000compas_pb1.0 MB2.001×73.8 ms128.5 ms202.3 ms8.4826.9 MB0✓ yes
10,000compas_pb_zip503.6 KB4.23×87.3 ms130.8 ms218.1 ms3.9438.0 MB0✓ yes
10,000compas_pb_zstd486.6 KB4.378×78.5 ms129.2 ms207.7 ms3.8568.0 MB0✓ yes
10,000compas_msgpack1.4 MB1.525×48.0 ms132.5 ms180.5 ms10.79216.1 MB0✓ yes
10,000compas_msgpack_zstd751.3 KB2.835×67.8 ms141.1 ms208.9 ms5.45217.4 MB0✓ yes

mesh

Round-trip time
1,000 elements
json
5.1 ms
json_zip
7.3 ms
compas_pb
5.0 ms
compas_pb_zip
5.7 ms
compas_pb_zstd
5.4 ms
compas_msgpack
8.0 ms
compas_msgpack_zstd
8.5 ms
10,000 elements
json
60.6 ms
json_zip
83.0 ms
compas_pb
51.6 ms
compas_pb_zip
58.4 ms
compas_pb_zstd
53.2 ms
compas_msgpack
93.2 ms
compas_msgpack_zstd
95.5 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
32.1 KB
compas_pb_zip
15.9 KB
compas_pb_zstd
15.8 KB
compas_msgpack
57.3 KB
compas_msgpack_zstd
24.5 KB
10,000 elements
json
864.1 KB
json_zip
238.2 KB
compas_pb
320.3 KB
compas_pb_zip
158.5 KB
compas_pb_zstd
168.6 KB
compas_msgpack
606.5 KB
compas_msgpack_zstd
198.8 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.5 ms3.6 ms5.1 ms22.8231.5 MB0✓ yes
1,000json_zip27.4 KB2.929×3.5 ms3.8 ms7.3 ms7.4691.5 MB0✓ yes
1,000compas_pb32.1 KB2.496×1.7 ms3.3 ms5.0 ms10.035857.4 KB0✓ yes
1,000compas_pb_zip15.9 KB5.031×2.3 ms3.4 ms5.7 ms4.813890.9 KB0✓ yes
1,000compas_pb_zstd15.8 KB5.07×2.1 ms3.3 ms5.4 ms4.881889.6 KB0✓ yes
1,000compas_msgpack57.3 KB1.4×0.4 ms7.5 ms8.0 ms7.7892.0 MB0✓ yes
1,000compas_msgpack_zstd24.5 KB3.269×1.0 ms7.5 ms8.5 ms3.3642.0 MB0✓ yes
10,000json864.1 KB1.0×16.4 ms44.2 ms60.6 ms20.03115.3 MB0✓ yes
10,000json_zip238.2 KB3.629×39.1 ms43.9 ms83.0 ms5.56115.3 MB0✓ yes
10,000compas_pb320.3 KB2.698×17.0 ms34.5 ms51.6 ms9.4998.3 MB0✓ yes
10,000compas_pb_zip158.5 KB5.453×23.8 ms34.5 ms58.4 ms4.6978.6 MB0✓ yes
10,000compas_pb_zstd168.6 KB5.125×19.9 ms33.3 ms53.2 ms5.1798.6 MB0✓ yes
10,000compas_msgpack606.5 KB1.425×4.9 ms88.3 ms93.2 ms7.03319.6 MB0✓ yes
10,000compas_msgpack_zstd198.8 KB4.348×8.4 ms87.1 ms95.5 ms2.33720.2 MB0✓ yes

mesh_attrs

Round-trip time
1,000 elements
json
5.9 ms
json_zip
8.4 ms
compas_pb
5.6 ms
compas_pb_zip
6.1 ms
compas_pb_zstd
5.7 ms
compas_msgpack
8.5 ms
compas_msgpack_zstd
9.4 ms
10,000 elements
json
68.4 ms
json_zip
102.8 ms
compas_pb
55.2 ms
compas_pb_zip
69.9 ms
compas_pb_zstd
56.8 ms
compas_msgpack
97.2 ms
compas_msgpack_zstd
100.0 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
40.2 KB
compas_pb_zip
23.7 KB
compas_pb_zstd
23.7 KB
compas_msgpack
74.3 KB
compas_msgpack_zstd
33.0 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
398.5 KB
compas_pb_zip
232.9 KB
compas_pb_zstd
233.3 KB
compas_msgpack
772.5 KB
compas_msgpack_zstd
275.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×2.0 ms3.9 ms5.9 ms28.6391.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.4 ms3.9 ms8.4 ms9.6651.6 MB0✓ yes
1,000compas_pb40.2 KB2.726×2.0 ms3.6 ms5.6 ms11.475945.2 KB0✓ yes
1,000compas_pb_zip23.7 KB4.611×2.6 ms3.5 ms6.1 ms6.92986.7 KB0✓ yes
1,000compas_pb_zstd23.7 KB4.617×2.3 ms3.4 ms5.7 ms7.169985.4 KB0✓ yes
1,000compas_msgpack74.3 KB1.474×0.4 ms8.0 ms8.5 ms9.4932.0 MB0✓ yes
1,000compas_msgpack_zstd33.0 KB3.317×1.3 ms8.1 ms9.4 ms4.1722.1 MB0✓ yes
10,000json1.1 MB1.0×19.8 ms48.6 ms68.4 ms24.22415.8 MB0✓ yes
10,000json_zip338.9 KB3.393×51.3 ms51.5 ms102.8 ms6.73915.8 MB0✓ yes
10,000compas_pb398.5 KB2.886×20.0 ms35.2 ms55.2 ms11.5999.2 MB0✓ yes
10,000compas_pb_zip232.9 KB4.936×28.8 ms41.1 ms69.9 ms5.8039.5 MB0✓ yes
10,000compas_pb_zstd233.3 KB4.929×22.3 ms34.5 ms56.8 ms6.9259.5 MB0✓ yes
10,000compas_msgpack772.5 KB1.489×4.5 ms92.7 ms97.2 ms8.53819.9 MB0✓ yes
10,000compas_msgpack_zstd275.5 KB4.175×10.2 ms89.9 ms100.0 ms3.13820.6 MB0✓ yes

planes

Round-trip time
1,000 elements
json
13.7 ms
json_zip
18.8 ms
compas_pb
17.7 ms
compas_pb_zip
18.7 ms
compas_pb_zstd
18.9 ms
compas_msgpack
15.0 ms
compas_msgpack_zstd
16.4 ms
10,000 elements
json
148.8 ms
json_zip
200.9 ms
compas_pb
176.4 ms
compas_pb_zip
202.9 ms
compas_pb_zstd
190.3 ms
compas_msgpack
157.6 ms
compas_msgpack_zstd
181.0 ms
Wire size
1,000 elements
json
219.9 KB
json_zip
85.4 KB
compas_pb
107.4 KB
compas_pb_zip
51.1 KB
compas_pb_zstd
49.4 KB
compas_msgpack
143.6 KB
compas_msgpack_zstd
77.5 KB
10,000 elements
json
2.1 MB
json_zip
846.3 KB
compas_pb
1.0 MB
compas_pb_zip
508.5 KB
compas_pb_zstd
497.0 KB
compas_msgpack
1.4 MB
compas_msgpack_zstd
761.9 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json219.9 KB1.0×5.4 ms8.3 ms13.7 ms27.1181.0 MB2.2e-16✗ no
1,000json_zip85.4 KB2.574×10.0 ms8.8 ms18.8 ms9.9031.0 MB2.2e-16✗ no
1,000compas_pb107.4 KB2.046×4.7 ms13.0 ms17.7 ms8.444705.7 KB2.2e-16✗ no
1,000compas_pb_zip51.1 KB4.305×6.1 ms12.6 ms18.7 ms4.138814.4 KB2.2e-16✗ no
1,000compas_pb_zstd49.4 KB4.448×5.7 ms13.2 ms18.9 ms3.841813.2 KB2.2e-16✗ no
1,000compas_msgpack143.6 KB1.532×2.5 ms12.4 ms15.0 ms11.8111.6 MB2.2e-16✗ no
1,000compas_msgpack_zstd77.5 KB2.837×4.0 ms12.3 ms16.4 ms6.4351.7 MB2.2e-16✗ no
10,000json2.1 MB1.0×54.7 ms94.1 ms148.8 ms23.92910.0 MB2.2e-16✗ no
10,000json_zip846.3 KB2.599×100.5 ms100.5 ms200.9 ms8.62610.0 MB2.2e-16✗ no
10,000compas_pb1.0 MB2.047×46.0 ms130.4 ms176.4 ms8.4386.9 MB2.2e-16✗ no
10,000compas_pb_zip508.5 KB4.325×62.1 ms140.8 ms202.9 ms3.6998.0 MB2.2e-16✗ no
10,000compas_pb_zstd497.0 KB4.425×56.2 ms134.1 ms190.3 ms3.7958.0 MB2.2e-16✗ no
10,000compas_msgpack1.4 MB1.532×24.2 ms133.4 ms157.6 ms11.0216.1 MB2.2e-16✗ no
10,000compas_msgpack_zstd761.9 KB2.887×39.6 ms141.4 ms181.0 ms5.51817.5 MB2.2e-16✗ no

pointcloud

Round-trip time
10,000 elements
json
26.6 ms
json_zip
47.8 ms
compas_pb
13.6 ms
compas_pb_zip
20.4 ms
compas_pb_zstd
15.0 ms
compas_msgpack
30.6 ms
compas_msgpack_zstd
37.3 ms
100,000 elements
json
339.2 ms
json_zip
564.1 ms
compas_pb
190.6 ms
compas_pb_zip
271.0 ms
compas_pb_zstd
205.8 ms
compas_msgpack
402.4 ms
compas_msgpack_zstd
453.6 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
234.4 KB
compas_pb_zip
223.4 KB
compas_pb_zstd
222.4 KB
compas_msgpack
273.5 KB
compas_msgpack_zstd
244.9 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
2.3 MB
compas_pb_zip
2.2 MB
compas_pb_zstd
2.2 MB
compas_msgpack
2.7 MB
compas_msgpack_zstd
2.3 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.3 ms13.3 ms26.6 ms43.684.1 MB0✓ yes
10,000json_zip274.1 KB2.068×33.3 ms14.5 ms47.8 ms19.2974.1 MB0✓ yes
10,000compas_pb234.4 KB2.419×3.1 ms10.5 ms13.6 ms22.7783.4 MB0✓ yes
10,000compas_pb_zip223.4 KB2.538×9.2 ms11.2 ms20.4 ms20.393.7 MB0✓ yes
10,000compas_pb_zstd222.4 KB2.549×3.3 ms11.7 ms15.0 ms19.5433.7 MB0✓ yes
10,000compas_msgpack273.5 KB2.073×3.7 ms27.0 ms30.6 ms10.3844.4 MB0✓ yes
10,000compas_msgpack_zstd244.9 KB2.315×4.7 ms32.6 ms37.3 ms7.6984.6 MB0✓ yes
100,000json5.5 MB1.0×150.7 ms188.5 ms339.2 ms30.79140.6 MB0✓ yes
100,000json_zip2.7 MB2.079×354.5 ms209.6 ms564.1 ms13.32240.6 MB0✓ yes
100,000compas_pb2.3 MB2.419×32.0 ms158.6 ms190.6 ms15.12834.3 MB0✓ yes
100,000compas_pb_zip2.2 MB2.539×94.4 ms176.6 ms271.0 ms12.94636.6 MB0✓ yes
100,000compas_pb_zstd2.2 MB2.549×35.0 ms170.8 ms205.8 ms13.33136.6 MB0✓ yes
100,000compas_msgpack2.7 MB2.073×49.0 ms353.4 ms402.4 ms7.92443.5 MB0✓ yes
100,000compas_msgpack_zstd2.3 MB2.362×82.4 ms371.3 ms453.6 ms6.61946.2 MB0✓ yes

points

Round-trip time
1,000 elements
json
7.6 ms
json_zip
10.2 ms
compas_pb
8.8 ms
compas_pb_zip
9.3 ms
compas_pb_zstd
8.8 ms
compas_msgpack
7.0 ms
compas_msgpack_zstd
8.0 ms
10,000 elements
json
72.9 ms
json_zip
99.1 ms
compas_pb
80.8 ms
compas_pb_zip
93.1 ms
compas_pb_zstd
85.6 ms
compas_msgpack
78.1 ms
compas_msgpack_zstd
91.3 ms
Wire size
1,000 elements
json
141.7 KB
json_zip
54.6 KB
compas_pb
77.2 KB
compas_pb_zip
25.5 KB
compas_pb_zstd
24.4 KB
compas_msgpack
102.5 KB
compas_msgpack_zstd
50.6 KB
10,000 elements
json
1.4 MB
json_zip
539.8 KB
compas_pb
771.5 KB
compas_pb_zip
252.6 KB
compas_pb_zstd
241.6 KB
compas_msgpack
1.0 MB
compas_msgpack_zstd
499.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json141.7 KB1.0×3.9 ms3.6 ms7.6 ms40.168500.8 KB0✓ yes
1,000json_zip54.6 KB2.593×6.1 ms4.1 ms10.2 ms13.714503.2 KB0✓ yes
1,000compas_pb77.2 KB1.836×3.6 ms5.2 ms8.8 ms15.233260.1 KB0✓ yes
1,000compas_pb_zip25.5 KB5.559×4.2 ms5.1 ms9.3 ms5.097338.5 KB0✓ yes
1,000compas_pb_zstd24.4 KB5.812×3.9 ms4.9 ms8.8 ms5.081337.3 KB0✓ yes
1,000compas_msgpack102.5 KB1.382×1.7 ms5.3 ms7.0 ms19.826804.8 KB0✓ yes
1,000compas_msgpack_zstd50.6 KB2.798×2.8 ms5.2 ms8.0 ms9.981909.3 KB0✓ yes
10,000json1.4 MB1.0×35.4 ms37.5 ms72.9 ms38.7034.9 MB0✓ yes
10,000json_zip539.8 KB2.624×59.7 ms39.4 ms99.1 ms14.0344.9 MB0✓ yes
10,000compas_pb771.5 KB1.836×32.2 ms48.5 ms80.8 ms16.2832.6 MB0✓ yes
10,000compas_pb_zip252.6 KB5.609×42.7 ms50.4 ms93.1 ms5.1283.3 MB0✓ yes
10,000compas_pb_zstd241.6 KB5.863×37.0 ms48.6 ms85.6 ms5.0893.3 MB0✓ yes
10,000compas_msgpack1.0 MB1.381×16.8 ms61.4 ms78.1 ms17.118.1 MB0✓ yes
10,000compas_msgpack_zstd499.7 KB2.835×28.4 ms62.8 ms91.3 ms8.1419.1 MB0✓ yes

spheres

Round-trip time
1,000 elements
json
46.4 ms
json_zip
48.7 ms
compas_pb
54.4 ms
compas_pb_zip
54.2 ms
compas_pb_zstd
52.6 ms
compas_msgpack
50.6 ms
compas_msgpack_zstd
50.9 ms
10,000 elements
json
479.8 ms
json_zip
512.8 ms
compas_pb
545.1 ms
compas_pb_zip
553.1 ms
compas_pb_zstd
556.8 ms
compas_msgpack
525.7 ms
compas_msgpack_zstd
566.9 ms
Wire size
1,000 elements
json
231.7 KB
json_zip
66.7 KB
compas_pb
112.3 KB
compas_pb_zip
34.3 KB
compas_pb_zstd
32.4 KB
compas_msgpack
199.2 KB
compas_msgpack_zstd
60.8 KB
10,000 elements
json
2.3 MB
json_zip
661.5 KB
compas_pb
1.1 MB
compas_pb_zip
340.4 KB
compas_pb_zstd
326.9 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
594.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json231.7 KB1.0×7.8 ms38.6 ms46.4 ms6.141.6 MB0✓ yes
1,000json_zip66.7 KB3.474×9.5 ms39.1 ms48.7 ms1.7451.6 MB0✓ yes
1,000compas_pb112.3 KB2.063×7.3 ms47.1 ms54.4 ms2.4421.2 MB0✓ yes
1,000compas_pb_zip34.3 KB6.756×7.8 ms46.4 ms54.2 ms0.7571.3 MB0✓ yes
1,000compas_pb_zstd32.4 KB7.145×7.4 ms45.2 ms52.6 ms0.7341.3 MB0✓ yes
1,000compas_msgpack199.2 KB1.163×3.8 ms46.8 ms50.6 ms4.3592.5 MB0✓ yes
1,000compas_msgpack_zstd60.8 KB3.813×4.9 ms46.0 ms50.9 ms1.3532.7 MB0✓ yes
10,000json2.3 MB1.0×68.7 ms411.1 ms479.8 ms5.77115.6 MB0✓ yes
10,000json_zip661.5 KB3.502×100.8 ms412.0 ms512.8 ms1.64415.6 MB0✓ yes
10,000compas_pb1.1 MB2.063×67.7 ms477.4 ms545.1 ms2.40912.4 MB0✓ yes
10,000compas_pb_zip340.4 KB6.805×81.8 ms471.3 ms553.1 ms0.7413.5 MB0✓ yes
10,000compas_pb_zstd326.9 KB7.086×77.6 ms479.2 ms556.8 ms0.69913.5 MB0✓ yes
10,000compas_msgpack1.9 MB1.163×32.2 ms493.4 ms525.7 ms4.13425.2 MB0✓ yes
10,000compas_msgpack_zstd594.7 KB3.896×50.7 ms516.2 ms566.9 ms1.1827.1 MB0✓ yes

vectors

Round-trip time
1,000 elements
json
7.8 ms
json_zip
10.6 ms
compas_pb
8.4 ms
compas_pb_zip
9.0 ms
compas_pb_zstd
8.8 ms
compas_msgpack
7.2 ms
compas_msgpack_zstd
8.4 ms
10,000 elements
json
74.1 ms
json_zip
104.1 ms
compas_pb
84.8 ms
compas_pb_zip
91.1 ms
compas_pb_zstd
87.9 ms
compas_msgpack
80.5 ms
compas_msgpack_zstd
102.4 ms
Wire size
1,000 elements
json
142.6 KB
json_zip
54.7 KB
compas_pb
78.1 KB
compas_pb_zip
25.5 KB
compas_pb_zstd
24.4 KB
compas_msgpack
103.5 KB
compas_msgpack_zstd
50.6 KB
10,000 elements
json
1.4 MB
json_zip
540.0 KB
compas_pb
781.3 KB
compas_pb_zip
252.6 KB
compas_pb_zstd
244.1 KB
compas_msgpack
1.0 MB
compas_msgpack_zstd
494.9 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json142.6 KB1.0×3.9 ms3.9 ms7.8 ms37.727501.8 KB0✓ yes
1,000json_zip54.7 KB2.609×6.0 ms4.5 ms10.6 ms12.365504.2 KB0✓ yes
1,000compas_pb78.1 KB1.826×3.3 ms5.1 ms8.4 ms15.722260.1 KB0✓ yes
1,000compas_pb_zip25.5 KB5.597×3.9 ms5.1 ms9.0 ms5.088339.4 KB0✓ yes
1,000compas_pb_zstd24.4 KB5.852×3.8 ms5.0 ms8.8 ms4.959338.3 KB0✓ yes
1,000compas_msgpack103.5 KB1.378×1.8 ms5.4 ms7.2 ms19.534805.7 KB0✓ yes
1,000compas_msgpack_zstd50.6 KB2.818×2.8 ms5.5 ms8.4 ms9.395909.3 KB0✓ yes
10,000json1.4 MB1.0×35.2 ms38.9 ms74.1 ms37.5124.9 MB0✓ yes
10,000json_zip540.0 KB2.641×62.1 ms41.9 ms104.1 ms13.1844.9 MB0✓ yes
10,000compas_pb781.3 KB1.826×33.8 ms51.0 ms84.8 ms15.6922.6 MB0✓ yes
10,000compas_pb_zip252.6 KB5.647×39.9 ms51.2 ms91.1 ms5.053.4 MB0✓ yes
10,000compas_pb_zstd244.1 KB5.842×38.0 ms49.9 ms87.9 ms5.0123.4 MB0✓ yes
10,000compas_msgpack1.0 MB1.378×17.0 ms63.5 ms80.5 ms16.6858.1 MB0✓ yes
10,000compas_msgpack_zstd494.9 KB2.882×31.8 ms70.5 ms102.4 ms7.1849.1 MB0✓ yes
\ No newline at end of file diff --git a/benchmarks/serialization/run.py b/benchmarks/serialization/run.py index 259f5d7858af..ae20a34e4ad6 100644 --- a/benchmarks/serialization/run.py +++ b/benchmarks/serialization/run.py @@ -37,9 +37,9 @@ # to any subject not given explicit sizes in PRESETS. # # The PRD (10.1) lists 5e6 vertices / 5e7 points as the largest sizes; the "full" preset caps -# at 1e6 / 1e7 so a run completes in reasonable time and memory on a workstation. The scaling -# trend for the N1 targets (binary/columnar vs JSON) is already clear at those sizes; bump the -# caps here for a machine that can take it. +# at 1e6 elements so a run completes in reasonable time and memory. (Larger sizes are dominated +# by the tracemalloc peak-memory probe, which traces every allocation during deserialize.) The +# binary-vs-JSON scaling trend for N1 is already clear across the 1e3 -> 1e6 sweep. DEFAULT_SIZES = { "quick": [1000, 10000], "full": [1000, 100000, 1000000], @@ -51,7 +51,7 @@ "full": { "mesh": [1000, 100000, 1000000], "mesh_attrs": [1000, 100000, 1000000], - "pointcloud": [10000, 1000000, 10000000], + "pointcloud": [10000, 100000, 1000000], }, } From d33431f66b8274c75bbf1d3eb82d0ba4e6e292cc Mon Sep 17 00:00:00 2001 From: Gonzalo Casas Date: Sat, 11 Jul 2026 08:21:05 +0200 Subject: [PATCH 09/13] Complete corpus (all 31 pb types) + type-coverage banner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the remaining geometry types so the corpus benchmarks all 31 of compas_pb's native serializable types: conics (arc/ellipse/parabola/hyperbola), solids (cylinder/cone/capsule/ torus), quaternion, and the transformation subtypes (translation/rotation/scale/shear/ reflection/projection). 32 subjects; all round-trip losslessly except the ~1e-16 quirks the fidelity check surfaces (frames/planes re-normalize axes — JSON too; rotation round-trips through axis+angle rather than the exact matrix). The report's executive summary gains a coverage banner (31/31 serializable types benchmarked), computed from compas_pb's SerializerRegistry vs the corpus fixture types. Co-Authored-By: Claude Opus 4.8 --- benchmarks/README.md | 39 +- benchmarks/serialization/fixtures.py | 60 +- benchmarks/serialization/report.py | 20 + .../serialization/results/baseline_quick.csv | 686 ++++++++++++------ .../serialization/results/baseline_quick.html | 6 +- .../serialization/results/samples/boxes.json | 4 +- .../results/samples/boxes.msgpack | Bin 461 -> 461 bytes .../results/samples/boxes.msgpack.json | 4 +- .../serialization/results/samples/graph.json | 2 +- .../results/samples/graph.msgpack | Bin 382 -> 382 bytes .../results/samples/graph.msgpack.json | 2 +- .../serialization/results/samples/graph.pb | Bin 255 -> 255 bytes .../results/samples/graph.pb.json | 6 +- .../serialization/results/samples/mesh.json | 2 +- .../results/samples/mesh.msgpack | Bin 496 -> 496 bytes .../results/samples/mesh.msgpack.json | 2 +- .../serialization/results/samples/mesh.pb | Bin 261 -> 261 bytes .../results/samples/mesh.pb.json | 6 +- .../results/samples/pointcloud.json | 2 +- .../results/samples/pointcloud.msgpack | Bin 203 -> 203 bytes .../results/samples/pointcloud.msgpack.json | 2 +- benchmarks/serialization/run.py | 25 + 22 files changed, 594 insertions(+), 274 deletions(-) diff --git a/benchmarks/README.md b/benchmarks/README.md index a4d730ebb0ea..eb213ebb28a0 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -25,18 +25,21 @@ For each **subject × size × format**: | `graph` | jittered grid, nodes (x,y,z) + edges | per-node coords | | `points`, `vectors`, `lines`, `frames`, `planes`, `boxes`, `spheres`, `circles` | a list of N primitives/shapes | — | | `polylines`, `polygons`, `beziers`, `polyhedrons` | a list of N compound objects (each holds several points) | — | -| `transformations` | a list of N 4×4 matrices | — | +| `arcs`, `ellipses`, `parabolas`, `hyperbolas` | a list of N conics | — | +| `cylinders`, `cones`, `capsules`, `toruses` | a list of N solids | — | +| `transformations`, `translations`, `rotations`, `scales`, `shears`, `reflections`, `projections`, `quaternions` | a list of N transforms/quaternions | — | ¹ The COMPAS `Pointcloud` type has no per-point attribute slot, so the "with per-element attributes" case lives on `mesh_attrs`. The primitive/shape subjects are **collections** (a Python `list` of N objects, a common -real-world payload — e.g. a list of frames as robot targets). The compound subjects -(polylines/polygons/beziers/polyhedrons) each hold several points, so they exercise -compas_pb's flat `repeated double` point arrays. This covers ~15 of compas_pb's ~31 native -geometry types; still uncovered: the conics (Arc/Ellipse/Parabola/Hyperbola), the remaining -shapes (Cylinder/Cone/Capsule/Torus), Quaternion, and the specific transformation subtypes -(Translation/Rotation/Scale/… — which have their own proto messages beyond the base matrix). +real-world payload — e.g. a list of frames as robot targets). The compound subjects each +hold several points, exercising compas_pb's flat `repeated double` point arrays. **The corpus +now benchmarks all 31 of compas_pb's native serializable types** (the report shows a live +coverage banner). All round-trip losslessly except a few ~1e-16 quirks the fidelity check +surfaces: `frames`/`planes` (COMPAS re-normalizes axes on construction — affects JSON too) and +`rotations` (compas_pb's `Rotation` serializer round-trips through axis+angle, not the exact +matrix, so it isn't bit-reproduced). Fixtures are seeded ([`fixtures.py`](serialization/fixtures.py)) so runs are comparable and reused across every format; the harness measures a list or a single `Data` object @@ -205,18 +208,20 @@ every allocation on deserialize — dominates runtime. Swap it for RSS sampling JSON because each element goes through registry lookup + message unpack. A batched/columnar encoding for homogeneous primitive lists (e.g. N points/frames as flat arrays) would close it, the same way the mesh/graph rewrites did. -2. **Mesh face/edge attributes** — still stored as `map` (cheap when empty, - which is the common case). Could reuse the columnar layout when populated; low priority - since the corpus doesn't exercise face/edge attributes. -3. **Compare against MsgSpec** — evaluate the Kumiki-project MsgSpec-based serialization as an - additional format (next step). +2. **`Rotation` serializer** — stores axis + angle, so the 4×4 matrix isn't bit-reproduced on + round-trip (~1e-16 error; `rotations` shows `lossless=no`). Storing the matrix directly (as + `Transformation` does) would make it exact. +3. **PRD-scale memory (5e6/5e7)** — the `--preset full` run caps at 1e6 because the + `tracemalloc` peak-memory probe traces every allocation; swap it for RSS sampling to push + to the PRD's largest sizes. ## Status Phase 1: baseline harness + JSON numbers, plus `Data.canonical_hash()` decoupling object identity from the JSON text (`sha256()` is unchanged). -Phase 2 (in progress): `compas_pb` measured and **optimized** — double precision, flat -coordinate arrays, inline attribute maps, explicit int/float, CSR faces — now a fully -**lossless** binary mode, smaller and faster than JSON on numeric data. Still open: a real -version-compat policy and reducing per-type boilerplate. -N1 speed/memory targets for the columnar direction will be set from these baselines. +Phase 2: `compas_pb` measured and **optimized** — double precision, flat coordinate arrays, +columnar attributes (mesh vertices/faces/edges, graph nodes/edges), explicit int/float, CSR +faces, guid/name omission, msgpack comparison. Now a **lossless** binary mode, **smaller and +faster than JSON** on numeric data (**N1 met** — see the full-preset table). All **31** +serializable types benchmarked. The wire-version check is a **hard gate** (PRD N4) — the +version bump that activates rejection of older data happens at release. diff --git a/benchmarks/serialization/fixtures.py b/benchmarks/serialization/fixtures.py index 0c5c2b7129e5..0cb9fe0efdbd 100644 --- a/benchmarks/serialization/fixtures.py +++ b/benchmarks/serialization/fixtures.py @@ -19,19 +19,34 @@ from compas.datastructures import Graph from compas.datastructures import Mesh +from compas.geometry import Arc from compas.geometry import Bezier from compas.geometry import Box +from compas.geometry import Capsule from compas.geometry import Circle +from compas.geometry import Cone +from compas.geometry import Cylinder +from compas.geometry import Ellipse from compas.geometry import Frame +from compas.geometry import Hyperbola from compas.geometry import Line +from compas.geometry import Parabola from compas.geometry import Plane from compas.geometry import Point from compas.geometry import Pointcloud from compas.geometry import Polygon from compas.geometry import Polyhedron from compas.geometry import Polyline +from compas.geometry import Projection +from compas.geometry import Quaternion +from compas.geometry import Reflection +from compas.geometry import Rotation +from compas.geometry import Scale +from compas.geometry import Shear from compas.geometry import Sphere +from compas.geometry import Torus from compas.geometry import Transformation +from compas.geometry import Translation from compas.geometry import Vector DEFAULT_SEED = 42 @@ -131,6 +146,12 @@ def _make_primitive(kind, rng): def coord(): return [rng.uniform(-100.0, 100.0) for _ in range(3)] + def frame(): + # Axis-aligned (only translated): a jittered frame re-normalizes with ~1e-16 error on + # round-trip (a COMPAS construction quirk, exercised by the `frames` subject itself), which + # would otherwise mask the losslessness of the shape/conic placed on it. + return Frame(coord(), [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]) + if kind == "point": return Point(*coord()) if kind == "vector": @@ -161,7 +182,40 @@ def coord(): if kind == "polyhedron": return Polyhedron([coord() for _ in range(4)], [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]) if kind == "transformation": - return Transformation.from_frame(Frame(coord(), [1.0, 0.1, 0.0], [0.0, 1.0, 0.1])) + return Transformation.from_frame(frame()) + # Conics + if kind == "arc": + return Arc(radius=rng.uniform(1.0, 9.0), start_angle=0.2, end_angle=1.5, frame=frame()) + if kind == "ellipse": + return Ellipse(major=rng.uniform(3.0, 9.0), minor=rng.uniform(1.0, 3.0), frame=frame()) + if kind == "parabola": + return Parabola(focal=rng.uniform(1.0, 5.0), frame=frame()) + if kind == "hyperbola": + return Hyperbola(major=rng.uniform(3.0, 9.0), minor=rng.uniform(1.0, 3.0), frame=frame()) + # Solids + if kind == "cylinder": + return Cylinder(radius=rng.uniform(1.0, 5.0), height=rng.uniform(2.0, 9.0), frame=frame()) + if kind == "cone": + return Cone(radius=rng.uniform(1.0, 5.0), height=rng.uniform(2.0, 9.0), frame=frame()) + if kind == "capsule": + return Capsule(radius=rng.uniform(1.0, 3.0), height=rng.uniform(2.0, 9.0), frame=frame()) + if kind == "torus": + return Torus(radius_axis=rng.uniform(3.0, 9.0), radius_pipe=rng.uniform(1.0, 2.0), frame=frame()) + # Quaternion + transformation subtypes (each has its own proto message) + if kind == "quaternion": + return Quaternion(1.0 + rng.uniform(-0.3, 0.3), *coord()).unitized() + if kind == "translation": + return Translation.from_vector(coord()) + if kind == "rotation": + return Rotation.from_axis_and_angle([0.0, 0.0, 1.0], rng.uniform(0.1, 3.0)) + if kind == "scale": + return Scale.from_factors([rng.uniform(0.5, 3.0) for _ in range(3)]) + if kind == "shear": + return Shear.from_angle_direction_plane(rng.uniform(0.1, 0.8), [1.0, 0.0, 0.0], Plane([0, 0, 0], [0, 0, 1])) + if kind == "reflection": + return Reflection.from_plane(Plane(coord(), [0.0, 0.0, 1.0])) + if kind == "projection": + return Projection.from_plane(Plane(coord(), [0.0, 0.0, 1.0])) raise ValueError("Unknown primitive kind: {}".format(kind)) @@ -189,6 +243,8 @@ def make_primitives(kind, count, seed=DEFAULT_SEED): _PRIMITIVE_KINDS = [ "point", "vector", "line", "frame", "plane", "box", "sphere", "circle", "polyline", "polygon", "bezier", "polyhedron", "transformation", + "arc", "ellipse", "parabola", "hyperbola", "cylinder", "cone", "capsule", "torus", + "quaternion", "translation", "rotation", "scale", "shear", "reflection", "projection", ] @@ -202,5 +258,5 @@ def make_primitives(kind, count, seed=DEFAULT_SEED): } # One subject per primitive kind (pluralized label), each a list of `size` primitives. for _kind in _PRIMITIVE_KINDS: - _label = _kind + ("es" if _kind.endswith("x") else "s") + _label = _kind + ("es" if _kind.endswith(("x", "s")) else "s") SUBJECTS[_label] = (lambda k: lambda size, seed=DEFAULT_SEED: make_primitives(k, size, seed=seed))(_kind) diff --git a/benchmarks/serialization/report.py b/benchmarks/serialization/report.py index 610c28ed683e..02d5a486ec7e 100644 --- a/benchmarks/serialization/report.py +++ b/benchmarks/serialization/report.py @@ -237,6 +237,10 @@ def _css(colors): .segmented button.active { background: var(--surface); color: var(--text-primary); font-weight: 600; box-shadow: 0 1px 2px rgba(0,0,0,0.10); } .tile .rng { font-size: 11px; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; } +.coverage { margin: 18px 0 0; font-size: 13px; color: var(--text-secondary); + background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 12px 16px; } +.coverage b { color: var(--text-primary); font-weight: 650; } +.coverage .miss { color: var(--muted); font-size: 12px; } """.replace("%SERIES_LIGHT%", series_light).replace("%SERIES_DARK%", series_dark) @@ -335,6 +339,21 @@ def _table(subject_rows, colors): return '
{}{}
'.format(head, "".join(body)) +def _coverage_banner(coverage): + """Static banner: how many of compas_pb's serializable types the corpus benchmarks.""" + if not coverage: + return "" + n, total = coverage["benchmarked"], coverage["serializable"] + missing = coverage.get("missing") or [] + if missing: + tail = ' not yet covered: {}'.format(html.escape(", ".join(missing))) + else: + tail = " — full coverage." + return '
{}/{} of compas_pb\'s serializable types are benchmarked.{}
'.format( + n, total, tail + ) + + def build_html(rows, meta=None): """Return a full standalone HTML document for the given result rows. @@ -372,6 +391,7 @@ def build_html(rows, meta=None): ) sections = [ controls, + _coverage_banner(meta.get("coverage")), '
', _legend(rows, colors), ] diff --git a/benchmarks/serialization/results/baseline_quick.csv b/benchmarks/serialization/results/baseline_quick.csv index 4eb1b7deda18..b813daead11d 100644 --- a/benchmarks/serialization/results/baseline_quick.csv +++ b/benchmarks/serialization/results/baseline_quick.csv @@ -1,239 +1,449 @@ subject,size,format,size_bytes,compression_vs_json,dump_median_s,dump_stdev_s,load_median_s,load_stdev_s,roundtrip_median_s,dump_mb_s,load_mb_s,peak_mem_bytes,lossless,data_equal,canonical_hash_equal,max_abs_error,rms_error,note -beziers,1000,json,333223,1.0,0.008053,0.001805,0.009788,0.000363,0.017841,41.379,34.043,1769015,True,True,True,0.0,0.0,"compact text, lossless" -beziers,1000,json_zip,145252,2.294,0.016243,0.001289,0.010026,0.00014,0.026269,8.942,14.488,1771520,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -beziers,1000,compas_pb,155015,2.15,0.004889,0.016199,0.010363,0.000114,0.015253,31.705,14.958,1334485,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -beziers,1000,compas_pb_zip,93529,3.563,0.006915,0.000153,0.010848,0.002825,0.017763,13.526,8.622,1490728,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -beziers,1000,compas_pb_zstd,92304,3.61,0.005847,0.000791,0.010976,0.002813,0.016823,15.786,8.41,1489533,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -beziers,1000,compas_msgpack,199003,1.674,0.002952,0.001526,0.016482,0.00314,0.019434,67.412,12.074,2458467,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -beziers,1000,compas_msgpack_zstd,128826,2.587,0.005413,0.001538,0.016909,0.003196,0.022322,23.801,7.619,2657039,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -beziers,10000,json,3332149,1.0,0.084562,0.014893,0.115758,0.011194,0.200321,39.405,28.785,17768533,True,True,True,0.0,0.0,"compact text, lossless" -beziers,10000,json_zip,1443213,2.309,0.162178,0.014786,0.126444,0.001504,0.288622,8.899,11.414,17771030,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -beziers,10000,compas_pb,1550015,2.15,0.047374,0.000309,0.122872,0.001941,0.170246,32.719,12.615,13435021,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -beziers,10000,compas_pb_zip,933499,3.57,0.073697,0.001654,0.126436,0.011806,0.200133,12.667,7.383,14986264,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -beziers,10000,compas_pb_zstd,926258,3.597,0.0632,0.000191,0.124579,0.005258,0.187779,14.656,7.435,14985069,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -beziers,10000,compas_msgpack,1990003,1.674,0.030441,0.013809,0.210213,0.009641,0.240653,65.373,9.467,24790043,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -beziers,10000,compas_msgpack_zstd,1291176,2.581,0.048862,0.01491,0.200492,0.004164,0.249354,26.425,6.44,26780079,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -boxes,1000,json,285582,1.0,0.007315,0.001619,0.038544,3e-05,0.045859,39.04,7.409,1727364,True,True,True,0.0,0.0,"compact text, lossless" -boxes,1000,json_zip,89855,3.178,0.011275,0.002171,0.03897,0.000142,0.050245,7.969,2.306,1730085,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -boxes,1000,compas_pb,131015,2.18,0.006448,0.000149,0.044059,2.1e-05,0.050507,20.319,2.974,1339834,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -boxes,1000,compas_pb_zip,52308,5.46,0.008753,0.00021,0.044547,0.000133,0.0533,5.976,1.174,1472077,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -boxes,1000,compas_pb_zstd,50046,5.706,0.007797,0.00087,0.04526,0.003518,0.053057,6.419,1.106,1470882,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -boxes,1000,compas_msgpack,230003,1.242,0.003319,0.001527,0.045709,0.002939,0.049029,69.295,5.032,2664800,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -boxes,1000,compas_msgpack_zstd,79451,3.594,0.005382,0.001523,0.045574,0.003515,0.050956,14.763,1.743,2894372,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -boxes,10000,json,2855355,1.0,0.074427,0.016362,0.41365,0.002075,0.488077,38.365,6.903,17297673,True,True,True,0.0,0.0,"compact text, lossless" -boxes,10000,json_zip,891963,3.201,0.119041,0.017291,0.449364,0.012573,0.568405,7.493,1.985,17300170,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -boxes,10000,compas_pb,1310015,2.18,0.06711,0.000933,0.476184,0.00628,0.543294,19.521,2.751,13440506,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -boxes,10000,compas_pb_zip,520863,5.482,0.08087,0.000902,0.479365,0.006597,0.560234,6.441,1.087,14751629,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -boxes,10000,compas_pb_zstd,497195,5.743,0.080377,0.002135,0.471277,0.01144,0.551654,6.186,1.055,14750530,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -boxes,10000,compas_msgpack,2300003,1.241,0.034169,0.015722,0.506779,0.011271,0.540948,67.313,4.538,26841536,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -boxes,10000,compas_msgpack_zstd,795487,3.589,0.061757,0.024524,0.496986,0.009737,0.558743,12.881,1.601,29141572,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -circles,1000,json,237208,1.0,0.006606,0.002315,0.038653,0.003894,0.045259,35.907,6.137,1542873,True,True,True,0.0,0.0,"compact text, lossless" -circles,1000,json_zip,68256,3.475,0.009217,0.001763,0.038832,0.000104,0.048049,7.405,1.758,1545762,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -circles,1000,compas_pb,163015,1.455,0.007568,0.001971,0.045387,8e-05,0.052955,21.541,3.592,1358721,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -circles,1000,compas_pb_zip,63511,3.735,0.009595,0.001767,0.045852,5.9e-05,0.055447,6.619,1.385,1522960,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -circles,1000,compas_pb_zstd,62011,3.825,0.009048,0.001676,0.045625,0.002803,0.054673,6.853,1.359,1521769,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -circles,1000,compas_msgpack,204003,1.163,0.003179,0.001488,0.044433,0.0029,0.047612,64.173,4.591,2531491,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -circles,1000,compas_msgpack_zstd,62185,3.815,0.004723,0.001585,0.044486,0.003104,0.049209,13.168,1.398,2735527,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -circles,10000,json,2372279,1.0,0.066669,0.016652,0.408942,0.00181,0.47561,35.583,5.801,15454648,True,True,True,0.0,0.0,"compact text, lossless" -circles,10000,json_zip,677434,3.502,0.09812,0.015015,0.412371,0.003712,0.510491,6.904,1.643,15457153,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -circles,10000,compas_pb,1630015,1.455,0.076792,0.017032,0.482421,0.003404,0.559214,21.226,3.379,13630497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -circles,10000,compas_pb_zip,631718,3.755,0.102003,0.017806,0.493721,0.002114,0.595724,6.193,1.28,15261680,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -circles,10000,compas_pb_zstd,606552,3.911,0.090033,0.016918,0.488508,0.003028,0.578541,6.737,1.242,15260545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -circles,10000,compas_msgpack,2040003,1.163,0.033959,0.016078,0.492754,0.008114,0.526713,60.072,4.14,25510523,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -circles,10000,compas_msgpack_zstd,608987,3.895,0.046051,0.015785,0.48713,0.007126,0.533181,13.224,1.25,27551655,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -frames,1000,json,295873,1.0,0.007069,0.001622,0.019677,3.7e-05,0.026745,41.857,15.037,1384395,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"compact text, lossless" -frames,1000,json_zip,109781,2.695,0.0137,0.001559,0.02134,5.2e-05,0.03504,8.013,5.144,1386900,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"zip-compressed json, size baseline" -frames,1000,compas_pb,141015,2.098,0.00551,5.9e-05,0.025163,0.002682,0.030673,25.593,5.604,987572,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, double + flat arrays (optimized)" -frames,1000,compas_pb_zip,71467,4.14,0.007925,9e-05,0.025378,0.000133,0.033303,9.018,2.816,1129815,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zip-compressed" -frames,1000,compas_pb_zstd,69763,4.241,0.006724,0.000124,0.026123,0.002876,0.032846,10.376,2.671,1128620,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zstandard-compressed" -frames,1000,compas_msgpack,180003,1.644,0.002888,0.001394,0.024767,5.2e-05,0.027655,62.324,7.268,2083642,False,False,False,4.440892098500626e-16,6.299702658387308e-17,msgpack over the JSON-shape tree (Kumiki-style) -frames,1000,compas_msgpack_zstd,96626,3.062,0.004769,0.001488,0.025018,0.000209,0.029787,20.261,3.862,2261158,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"msgpack, zstandard-compressed" -frames,10000,json,2959373,1.0,0.079435,0.016291,0.215612,0.003767,0.295047,37.255,13.725,13880263,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"compact text, lossless" -frames,10000,json_zip,1090210,2.714,0.138246,0.016397,0.218419,0.002101,0.356666,7.886,4.991,13882936,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"zip-compressed json, size baseline" -frames,10000,compas_pb,1410015,2.099,0.059869,0.000532,0.265558,0.002933,0.325427,23.552,5.31,9920052,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, double + flat arrays (optimized)" -frames,10000,compas_pb_zip,712585,4.153,0.085895,0.001122,0.272389,0.000624,0.358284,8.296,2.616,11331295,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zip-compressed" -frames,10000,compas_pb_zstd,707041,4.186,0.067435,0.002162,0.269815,0.006557,0.33725,10.485,2.62,11330100,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zstandard-compressed" -frames,10000,compas_msgpack,1800003,1.644,0.031532,0.014811,0.290208,0.003166,0.32174,57.086,6.202,21017794,False,False,False,5.551115123125783e-16,6.326276205293956e-17,msgpack over the JSON-shape tree (Kumiki-style) -frames,10000,compas_msgpack_zstd,964070,3.07,0.053088,0.015512,0.287917,0.005105,0.341005,18.16,3.348,22817830,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"msgpack, zstandard-compressed" -graph,1000,json,76719,1.0,0.001786,7.7e-05,0.012365,3.5e-05,0.014151,42.962,6.204,1938217,True,True,True,0.0,0.0,"compact text, lossless" -graph,1000,json_zip,24330,3.153,0.003589,5.8e-05,0.012371,7.1e-05,0.01596,6.779,1.967,1940890,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -graph,1000,compas_pb,37178,2.064,0.004272,3.6e-05,0.003996,6.5e-05,0.008268,8.702,9.305,1115572,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -graph,1000,compas_pb_zip,15463,4.961,0.004811,6.9e-05,0.003851,3.1e-05,0.008662,3.214,4.015,1154146,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -graph,1000,compas_pb_zstd,16070,4.774,0.004275,1.7e-05,0.003752,6.6e-05,0.008027,3.759,4.283,1152783,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -graph,1000,compas_msgpack,53875,1.424,0.000596,1.4e-05,0.01428,0.00026,0.014876,90.451,3.773,2544153,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -graph,1000,compas_msgpack_zstd,17744,4.324,0.00122,2.6e-05,0.01462,0.00266,0.01584,14.545,1.214,2598061,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -graph,10000,json,793664,1.0,0.016456,0.000247,0.134153,0.004838,0.15061,48.228,5.916,19036162,True,True,True,0.0,0.0,"compact text, lossless" -graph,10000,json_zip,213387,3.719,0.034444,0.003612,0.125682,0.004374,0.160126,6.195,1.698,19020680,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -graph,10000,compas_pb,368817,2.152,0.040617,0.00036,0.037491,0.006643,0.078108,9.08,9.838,11049444,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -graph,10000,compas_pb_zip,142716,5.561,0.04711,0.000144,0.038196,0.00464,0.085306,3.029,3.736,11419653,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -graph,10000,compas_pb_zstd,185816,4.271,0.041276,0.000305,0.037137,0.004461,0.078413,4.502,5.004,11418294,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -graph,10000,compas_msgpack,564802,1.405,0.00665,0.003021,0.170606,0.009322,0.177255,84.937,3.311,25119679,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -graph,10000,compas_msgpack_zstd,118955,6.672,0.011698,0.003943,0.179458,0.0085,0.191156,10.169,0.663,25684514,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -lines,1000,json,218115,1.0,0.0079,0.001705,0.008041,0.000205,0.01594,27.611,27.126,1041873,True,True,True,0.0,0.0,"compact text, lossless" -lines,1000,json_zip,87005,2.507,0.012707,0.001701,0.008436,4.5e-05,0.021143,6.847,10.314,1044906,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -lines,1000,compas_pb,109015,2.001,0.006863,5.3e-05,0.011539,3.7e-05,0.018402,15.885,9.447,722835,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -lines,1000,compas_pb_zip,51798,4.211,0.008927,0.00068,0.012131,0.000327,0.021058,5.802,4.27,833078,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -lines,1000,compas_pb_zstd,50170,4.348,0.007774,9e-05,0.011629,3.9e-05,0.019403,6.454,4.314,831883,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -lines,1000,compas_msgpack,143003,1.525,0.004703,0.001558,0.011746,0.000194,0.016449,30.404,12.175,1663713,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -lines,1000,compas_msgpack_zstd,78603,2.775,0.006365,0.001657,0.011943,0.000225,0.018308,12.349,6.582,1806749,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -lines,10000,json,2181230,1.0,0.079982,0.016048,0.09071,0.005426,0.170692,27.271,24.046,10462004,True,True,True,0.0,0.0,"compact text, lossless" -lines,10000,json_zip,862939,2.528,0.122976,0.018102,0.098295,0.007233,0.221271,7.017,8.779,10464509,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -lines,10000,compas_pb,1090015,2.001,0.07221,0.000431,0.127358,0.005378,0.199568,15.095,8.559,7279619,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -lines,10000,compas_pb_zip,515699,4.23,0.086365,0.000856,0.124603,0.004662,0.210968,5.971,4.139,8370862,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -lines,10000,compas_pb_zstd,498282,4.378,0.078998,0.00135,0.127704,0.006328,0.206702,6.308,3.902,8369667,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -lines,10000,compas_msgpack,1430003,1.525,0.046774,0.014975,0.136317,0.00262,0.183091,30.573,10.49,16848977,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -lines,10000,compas_msgpack_zstd,769503,2.835,0.061887,0.015096,0.136837,0.002043,0.198725,12.434,5.623,18277541,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh,1000,json,82154,1.0,0.001784,0.00035,0.003741,6e-05,0.005525,46.058,21.96,1611855,True,True,True,0.0,0.0,"compact text, lossless" -mesh,1000,json_zip,28054,2.928,0.003763,0.000152,0.003807,0.000121,0.00757,7.456,7.369,1614336,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,1000,compas_pb,32913,2.496,0.001869,4.3e-05,0.003364,9.1e-05,0.005233,17.613,9.784,878003,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh,1000,compas_pb_zip,16331,5.031,0.002347,5.5e-05,0.003472,8.4e-05,0.005819,6.959,4.704,912312,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh,1000,compas_pb_zstd,16203,5.07,0.002041,3.7e-05,0.003661,0.000144,0.005702,7.94,4.426,910949,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh,1000,compas_msgpack,58668,1.4,0.000449,2.8e-05,0.00776,0.002811,0.00821,130.567,7.56,2063130,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh,1000,compas_msgpack_zstd,25135,3.269,0.001042,2.1e-05,0.007727,0.000128,0.008769,24.119,3.253,2121831,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh,10000,json,884888,1.0,0.016405,0.003335,0.045678,0.002961,0.062083,53.939,19.372,16027789,True,True,True,0.0,0.0,"compact text, lossless" -mesh,10000,json_zip,243867,3.629,0.040479,0.00069,0.043813,0.003245,0.084293,6.024,5.566,16035054,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh,10000,compas_pb,328024,2.698,0.0178,0.000198,0.035438,0.004142,0.053238,18.428,9.256,8718587,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh,10000,compas_pb_zip,162262,5.453,0.023866,0.000211,0.036516,0.004905,0.060383,6.799,4.444,9047715,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh,10000,compas_pb_zstd,172651,5.125,0.020953,0.000407,0.035712,0.003777,0.056666,8.24,4.835,9046644,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh,10000,compas_msgpack,621054,1.425,0.004525,0.000396,0.090281,0.001787,0.094806,137.255,6.879,20579024,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh,10000,compas_msgpack_zstd,203523,4.348,0.007804,0.000347,0.085776,0.001181,0.09358,26.079,2.373,21200111,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh_attrs,1000,json,112098,1.0,0.00183,4.2e-05,0.003787,6.7e-05,0.005617,61.249,29.6,1666431,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,1000,json_zip,38109,2.942,0.004363,7.1e-05,0.004169,0.000125,0.008532,8.735,9.141,1669096,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,1000,compas_pb,41120,2.726,0.001966,2.9e-05,0.003449,0.00247,0.005415,20.92,11.922,967891,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh_attrs,1000,compas_pb_zip,24312,4.611,0.002733,6.1e-05,0.003545,5.1e-05,0.006278,8.895,6.858,1010407,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh_attrs,1000,compas_pb_zstd,24277,4.617,0.002297,3.6e-05,0.003441,5.5e-05,0.005738,10.57,7.055,1009044,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh_attrs,1000,compas_msgpack,76076,1.474,0.000429,1.4e-05,0.008044,0.002594,0.008473,177.247,9.457,2087922,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh_attrs,1000,compas_msgpack_zstd,33791,3.317,0.001258,3.5e-05,0.008046,9.5e-05,0.009305,26.857,4.2,2164031,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -mesh_attrs,10000,json,1177508,1.0,0.019554,0.002963,0.046098,0.004152,0.065652,60.22,25.544,16560465,True,True,True,0.0,0.0,"compact text, lossless" -mesh_attrs,10000,json_zip,347076,3.393,0.047292,6.2e-05,0.046679,0.001569,0.093971,7.339,7.435,16563730,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -mesh_attrs,10000,compas_pb,408041,2.886,0.019859,0.002949,0.034536,0.004195,0.054395,20.547,11.815,9597267,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -mesh_attrs,10000,compas_pb_zip,238533,4.936,0.029333,0.000462,0.040921,0.00339,0.070254,8.132,5.829,10007512,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -mesh_attrs,10000,compas_pb_zstd,238887,4.929,0.022272,0.000145,0.035083,0.004233,0.057355,10.726,6.809,10005341,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -mesh_attrs,10000,compas_msgpack,791054,1.489,0.004344,6e-05,0.089806,0.001004,0.09415,182.111,8.808,20822216,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -mesh_attrs,10000,compas_msgpack_zstd,282067,4.175,0.011222,9.5e-05,0.092232,0.005109,0.103454,25.136,3.058,21611119,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -planes,1000,json,225141,1.0,0.005475,0.001531,0.008438,0.002697,0.013913,41.124,26.681,1048924,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"compact text, lossless" -planes,1000,json_zip,87412,2.576,0.00987,0.001539,0.008702,1.5e-05,0.018572,8.856,10.045,1051621,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"zip-compressed json, size baseline" -planes,1000,compas_pb,110015,2.046,0.00479,6.6e-05,0.012433,0.0027,0.017223,22.967,8.849,722652,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, double + flat arrays (optimized)" -planes,1000,compas_pb_zip,52297,4.305,0.006128,5.3e-05,0.012491,8.3e-05,0.01862,8.534,4.187,833895,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zip-compressed" -planes,1000,compas_pb_zstd,50611,4.448,0.00546,1.1e-05,0.012431,6.9e-05,0.017892,9.269,4.071,832700,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zstandard-compressed" -planes,1000,compas_msgpack,147003,1.532,0.002354,0.001437,0.011839,6.3e-05,0.014194,62.44,12.416,1664479,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,msgpack over the JSON-shape tree (Kumiki-style) -planes,1000,compas_msgpack_zstd,79332,2.838,0.003944,0.001443,0.011977,0.002898,0.015921,20.114,6.624,1811515,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"msgpack, zstandard-compressed" -planes,10000,json,2251968,1.0,0.054412,0.015752,0.096471,0.007461,0.150884,41.387,23.343,10532543,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"compact text, lossless" -planes,10000,json_zip,866765,2.598,0.098359,0.015385,0.098315,0.002762,0.196674,8.812,8.816,10535528,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"zip-compressed json, size baseline" -planes,10000,compas_pb,1100015,2.047,0.04917,0.000274,0.135197,0.005433,0.184367,22.372,8.136,7279204,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, double + flat arrays (optimized)" -planes,10000,compas_pb_zip,520659,4.325,0.062706,8.6e-05,0.130507,0.004233,0.193213,8.303,3.99,8380447,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zip-compressed" -planes,10000,compas_pb_zstd,508937,4.425,0.054706,0.000455,0.130808,0.004392,0.185514,9.303,3.891,8379252,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zstandard-compressed" -planes,10000,compas_msgpack,1470003,1.532,0.023675,0.014511,0.131108,0.001496,0.154784,62.09,11.212,16858631,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,msgpack over the JSON-shape tree (Kumiki-style) -planes,10000,compas_msgpack_zstd,780053,2.887,0.037661,0.014412,0.13805,0.001155,0.17571,20.713,5.651,18327187,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"msgpack, zstandard-compressed" -pointcloud,10000,json,580633,1.0,0.013356,0.002828,0.013528,0.002871,0.026884,43.473,42.921,4261534,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,10000,json_zip,280727,2.068,0.035566,0.001337,0.014714,0.00263,0.05028,7.893,19.079,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,10000,compas_pb,240074,2.419,0.003076,2.5e-05,0.010566,0.002776,0.013642,78.041,22.722,3599350,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -pointcloud,10000,compas_pb_zip,228795,2.538,0.009117,7.6e-05,0.01107,0.003169,0.020187,25.096,20.668,3840652,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -pointcloud,10000,compas_pb_zstd,227771,2.549,0.003334,2.6e-05,0.010746,0.002511,0.01408,68.323,21.195,3839561,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -pointcloud,10000,compas_msgpack,280093,2.073,0.003568,6.2e-05,0.027097,0.002654,0.030665,78.493,10.337,4570603,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -pointcloud,10000,compas_msgpack_zstd,250823,2.315,0.004644,0.000399,0.027967,0.003391,0.032611,54.015,8.968,4852841,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -pointcloud,100000,json,5804860,1.0,0.150311,0.002649,0.191948,0.001367,0.342259,38.619,30.242,42602609,True,True,True,0.0,0.0,"compact text, lossless" -pointcloud,100000,json_zip,2792760,2.079,0.352092,0.005212,0.187703,0.013331,0.539795,7.932,14.879,42599922,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -pointcloud,100000,compas_pb,2400078,2.419,0.0306,0.000112,0.151125,0.000633,0.181725,78.434,15.881,35996478,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -pointcloud,100000,compas_pb_zip,2286030,2.539,0.093928,0.000882,0.160119,0.002561,0.254047,24.338,14.277,38397656,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -pointcloud,100000,compas_pb_zstd,2276982,2.549,0.03412,0.000811,0.157367,0.002441,0.191487,66.735,14.469,38396589,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -pointcloud,100000,compas_msgpack,2800095,2.073,0.049369,0.005413,0.331642,0.01213,0.381011,56.718,8.443,45598691,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -pointcloud,100000,compas_msgpack_zstd,2457514,2.362,0.080575,0.000884,0.353567,0.007032,0.434142,30.5,6.951,48398819,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -points,1000,json,145071,1.0,0.003509,0.001437,0.003686,8.9e-05,0.007195,41.347,39.354,512438,True,True,True,0.0,0.0,"compact text, lossless" -points,1000,json_zip,55990,2.591,0.005809,0.001406,0.003825,8.9e-05,0.009633,9.639,14.64,514943,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -points,1000,compas_pb,79015,1.836,0.003233,3.7e-05,0.004766,4e-05,0.007999,24.438,16.58,266342,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -points,1000,compas_pb_zip,26095,5.559,0.00397,3.4e-05,0.004904,2.4e-05,0.008874,6.573,5.321,346581,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -points,1000,compas_pb_zstd,24960,5.812,0.003665,3.1e-05,0.004784,1.9e-05,0.008449,6.811,5.217,345390,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -points,1000,compas_msgpack,105003,1.382,0.001667,0.001429,0.005161,0.00011,0.006829,62.977,20.344,824071,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -points,1000,compas_msgpack_zstd,51865,2.797,0.002828,0.001367,0.005322,0.002501,0.008151,18.338,9.745,929571,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -points,10000,json,1450530,1.0,0.034953,0.014082,0.036641,0.004078,0.071595,41.499,39.587,5170601,True,True,True,0.0,0.0,"compact text, lossless" -points,10000,json_zip,552705,2.624,0.064172,0.011874,0.038685,0.004966,0.102857,8.613,14.287,5173106,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -points,10000,compas_pb,790015,1.836,0.03197,0.000242,0.047933,0.003068,0.079903,24.711,16.482,2718662,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -points,10000,compas_pb_zip,258617,5.609,0.040594,0.000693,0.050191,0.000683,0.090786,6.371,5.153,3510433,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -points,10000,compas_pb_zstd,247395,5.863,0.035943,0.000322,0.048346,0.002784,0.084289,6.883,5.117,3508710,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -points,10000,compas_msgpack,1050003,1.381,0.016601,0.013621,0.061133,0.002561,0.077734,63.25,17.176,8455711,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -points,10000,compas_msgpack_zstd,511417,2.836,0.026948,0.013793,0.060286,0.004142,0.087233,18.978,8.483,9505747,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -polygons,1000,json,450157,1.0,0.010854,0.002061,0.019155,0.002953,0.030009,41.474,23.501,2558352,True,True,True,0.0,0.0,"compact text, lossless" -polygons,1000,json_zip,202709,2.221,0.022638,0.001594,0.018982,0.002912,0.04162,8.954,10.679,2560857,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -polygons,1000,compas_pb,204015,2.206,0.005327,5.4e-05,0.018321,6.4e-05,0.023649,38.297,11.135,2007118,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -polygons,1000,compas_pb_zip,139427,3.229,0.00888,0.000124,0.019401,0.000488,0.028281,15.701,7.187,2212465,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -polygons,1000,compas_pb_zstd,138167,3.258,0.006613,0.00014,0.019799,0.003533,0.026412,20.893,6.978,2211166,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -polygons,1000,compas_msgpack,256003,1.758,0.00392,0.001408,0.028547,0.004206,0.032467,65.315,8.968,3309412,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -polygons,1000,compas_msgpack_zstd,178179,2.526,0.006667,0.001446,0.028091,0.0032,0.034758,26.727,6.343,3563984,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -polygons,10000,json,4502991,1.0,0.112961,0.01392,0.210527,0.003006,0.323488,39.863,21.389,25659610,True,True,True,0.0,0.0,"compact text, lossless" -polygons,10000,json_zip,2017012,2.233,0.228178,0.015428,0.218753,0.011442,0.446931,8.84,9.22,25662107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -polygons,10000,compas_pb,2040015,2.207,0.054759,0.000294,0.210319,0.005139,0.265078,37.254,9.7,20155542,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -polygons,10000,compas_pb_zip,1392267,3.234,0.091232,0.000744,0.212406,0.008573,0.303638,15.261,6.555,22196785,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -polygons,10000,compas_pb_zstd,1377765,3.268,0.068493,0.001219,0.21167,0.010215,0.280164,20.115,6.509,22195590,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -polygons,10000,compas_msgpack,2560003,1.759,0.037196,0.014469,0.337435,0.005699,0.374631,68.825,7.587,33279052,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -polygons,10000,compas_msgpack_zstd,1793895,2.51,0.062264,0.014073,0.339987,0.005353,0.402251,28.811,5.276,35840672,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -polyhedrons,1000,json,381223,1.0,0.007652,0.001535,0.006331,0.000196,0.013982,49.823,60.218,1840795,True,True,True,0.0,0.0,"compact text, lossless" -polyhedrons,1000,json_zip,146926,2.595,0.015272,0.001548,0.007007,0.003028,0.022279,9.621,20.968,1843300,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -polyhedrons,1000,compas_pb,185015,2.06,0.007758,9.7e-05,0.008143,0.003202,0.015901,23.849,22.72,1294035,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -polyhedrons,1000,compas_pb_zip,93696,4.069,0.00975,6.9e-05,0.008669,0.003007,0.01842,9.609,10.808,1481086,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -polyhedrons,1000,compas_pb_zstd,92462,4.123,0.008748,8.5e-05,0.008235,0.000104,0.016982,10.57,11.228,1479187,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -polyhedrons,1000,compas_msgpack,228003,1.672,0.001667,0.001374,0.020084,0.002944,0.02175,136.798,11.353,2893503,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -polyhedrons,1000,compas_msgpack_zstd,129213,2.95,0.003757,0.001371,0.020298,0.002851,0.024055,34.39,6.366,3121539,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -polyhedrons,10000,json,3812149,1.0,0.07813,0.013673,0.089729,0.004626,0.16786,48.792,42.485,18488497,True,True,True,0.0,0.0,"compact text, lossless" -polyhedrons,10000,json_zip,1461008,2.609,0.151673,0.014539,0.104054,0.013647,0.255726,9.633,14.041,18491002,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -polyhedrons,10000,compas_pb,1850015,2.061,0.078912,0.001643,0.106419,0.015543,0.185331,23.444,17.384,13034459,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -polyhedrons,10000,compas_pb_zip,934857,4.078,0.100031,0.000225,0.110484,0.011559,0.210515,9.346,8.461,14885950,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -polyhedrons,10000,compas_pb_zstd,929108,4.103,0.08776,0.000521,0.107464,0.012687,0.195224,10.587,8.646,14884507,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -polyhedrons,10000,compas_msgpack,2280003,1.672,0.017072,0.01343,0.263547,0.002455,0.280619,133.554,8.651,29149551,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -polyhedrons,10000,compas_msgpack_zstd,1293846,2.946,0.035365,0.018552,0.267279,0.018314,0.302644,36.586,4.841,31428635,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -polylines,1000,json,567347,1.0,0.013518,0.001676,0.015163,0.000485,0.028681,41.97,37.416,3091421,True,True,True,0.0,0.0,"compact text, lossless" -polylines,1000,json_zip,259494,2.186,0.029262,0.001644,0.015873,0.003194,0.045135,8.868,16.348,3094638,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -polylines,1000,compas_pb,253015,2.242,0.005903,9.1e-05,0.014154,0.000106,0.020058,42.859,17.875,2422895,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -polylines,1000,compas_pb_zip,185252,3.063,0.010635,5.7e-05,0.01472,0.003012,0.025355,17.419,12.585,2677942,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -polylines,1000,compas_pb_zstd,183803,3.087,0.007594,5.2e-05,0.014956,0.002434,0.02255,24.203,12.29,2675943,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -polylines,1000,compas_msgpack,313003,1.813,0.004412,0.001549,0.027059,0.003478,0.031471,70.947,11.568,3900909,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -polylines,1000,compas_msgpack_zstd,234107,2.423,0.006519,0.001552,0.027803,0.003176,0.034322,35.912,8.42,4213481,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -polylines,10000,json,5673763,1.0,0.139841,0.01487,0.180078,0.010341,0.319918,40.573,31.507,30990429,True,True,True,0.0,0.0,"compact text, lossless" -polylines,10000,json_zip,2584623,2.195,0.302751,0.011527,0.190907,0.013831,0.493658,8.537,13.539,30992926,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -polylines,10000,compas_pb,2530017,2.243,0.06205,0.000499,0.168124,0.013537,0.230174,40.774,15.049,24315487,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -polylines,10000,compas_pb_zip,1850649,3.066,0.109176,0.000522,0.180016,0.015054,0.289192,16.951,10.28,26846672,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -polylines,10000,compas_pb_zstd,1833306,3.095,0.077302,0.000578,0.171753,0.010044,0.249055,23.716,10.674,26845537,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -polylines,10000,compas_msgpack,3130003,1.813,0.044383,0.01987,0.340488,0.020104,0.384871,70.523,9.193,39209909,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -polylines,10000,compas_msgpack_zstd,2289784,2.478,0.07409,0.014597,0.351148,0.009403,0.425238,30.906,6.521,42340521,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -spheres,1000,json,237252,1.0,0.006457,0.00171,0.037608,0.000167,0.044064,36.746,6.309,1630917,True,True,True,0.0,0.0,"compact text, lossless" -spheres,1000,json_zip,68346,3.471,0.009261,0.00224,0.038384,0.000128,0.047646,7.38,1.781,1633422,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -spheres,1000,compas_pb,115015,2.063,0.006343,0.000152,0.045034,0.003502,0.051378,18.132,2.554,1291821,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -spheres,1000,compas_pb_zip,35118,6.756,0.007651,0.000683,0.044358,8e-05,0.052008,4.59,0.792,1408348,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -spheres,1000,compas_pb_zstd,33203,7.145,0.007232,7e-05,0.044133,0.000682,0.051366,4.591,0.752,1406869,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -spheres,1000,compas_msgpack,204003,1.163,0.003132,0.001571,0.044098,5.1e-05,0.04723,65.13,4.626,2619323,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -spheres,1000,compas_msgpack_zstd,62222,3.813,0.004717,0.001562,0.044309,0.000104,0.049026,13.19,1.404,2823359,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -spheres,10000,json,2372345,1.0,0.06542,0.016586,0.396201,0.001356,0.461621,36.263,5.988,16334546,True,True,True,0.0,0.0,"compact text, lossless" -spheres,10000,json_zip,677402,3.502,0.095117,0.021832,0.401387,0.004925,0.496504,7.122,1.688,16337051,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -spheres,10000,compas_pb,1150015,2.063,0.063511,0.000197,0.453103,0.010945,0.516613,18.107,2.538,12960429,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -spheres,10000,compas_pb_zip,348595,6.805,0.075044,0.001015,0.459728,0.004858,0.534772,4.645,0.758,14111616,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -spheres,10000,compas_pb_zstd,334774,7.086,0.072479,0.001112,0.458323,0.011566,0.530802,4.619,0.73,14110477,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -spheres,10000,compas_msgpack,2040003,1.163,0.03361,0.01705,0.476355,0.008071,0.509965,60.696,4.283,26391899,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -spheres,10000,compas_msgpack_zstd,609097,3.895,0.046622,0.016041,0.476749,0.013505,0.523371,13.065,1.278,28431935,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -transformations,1000,json,351071,1.0,0.006607,0.001718,0.005302,0.003144,0.011908,53.14,66.22,1426647,True,True,True,0.0,0.0,"compact text, lossless" -transformations,1000,json_zip,61305,5.727,0.009436,0.001413,0.005143,7.5e-05,0.014579,6.497,11.921,1429144,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -transformations,1000,compas_pb,195015,1.8,0.005503,7.2e-05,0.00696,8.1e-05,0.012463,35.44,28.019,973949,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -transformations,1000,compas_pb_zip,27972,12.551,0.00664,7e-05,0.006796,0.00012,0.013436,4.213,4.116,1170192,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -transformations,1000,compas_pb_zstd,24128,14.55,0.006794,7.7e-05,0.006674,8.6e-05,0.013468,3.551,3.615,1168997,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -transformations,1000,compas_msgpack,243003,1.445,0.001478,0.00144,0.014471,0.002808,0.015949,164.418,16.792,2137547,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -transformations,1000,compas_msgpack_zstd,52909,6.635,0.003239,0.001445,0.0133,0.002938,0.016539,16.336,3.978,2380583,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -transformations,10000,json,3510530,1.0,0.06795,0.013563,0.065274,0.009046,0.133224,51.664,53.781,14346826,True,True,True,0.0,0.0,"compact text, lossless" -transformations,10000,json_zip,608715,5.767,0.091882,0.014353,0.06447,0.006701,0.156351,6.625,9.442,14348995,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -transformations,10000,compas_pb,1950015,1.8,0.061022,0.005379,0.095173,0.012267,0.156194,31.956,20.489,9834437,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -transformations,10000,compas_pb_zip,276160,12.712,0.065256,0.000119,0.079394,0.006441,0.144651,4.232,3.478,11785680,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -transformations,10000,compas_pb_zstd,250340,14.023,0.070112,0.001604,0.077305,0.005821,0.147417,3.571,3.238,11784485,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -transformations,10000,compas_msgpack,2430003,1.445,0.014985,0.013363,0.169863,0.013262,0.184848,162.161,14.306,21587227,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -transformations,10000,compas_msgpack_zstd,515176,6.814,0.03113,0.014119,0.180689,0.015662,0.211819,16.549,2.851,24017263,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -vectors,1000,json,146071,1.0,0.00354,0.001471,0.003796,0.000116,0.007336,41.267,38.482,513823,True,True,True,0.0,0.0,"compact text, lossless" -vectors,1000,json_zip,55910,2.613,0.005814,0.001538,0.004024,0.000117,0.009838,9.616,13.894,516328,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -vectors,1000,compas_pb,80015,1.826,0.003267,1.4e-05,0.00491,1.5e-05,0.008177,24.492,16.296,266345,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -vectors,1000,compas_pb_zip,26096,5.597,0.003855,6.7e-05,0.005061,2.1e-05,0.008916,6.77,5.156,347588,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -vectors,1000,compas_pb_zstd,24962,5.852,0.003753,9.7e-05,0.005068,6.8e-05,0.00882,6.652,4.926,346393,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -vectors,1000,compas_msgpack,106003,1.378,0.001673,0.001409,0.005621,0.000268,0.007294,63.355,18.858,825072,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -vectors,1000,compas_msgpack_zstd,51808,2.819,0.002904,0.001582,0.005933,0.000263,0.008837,17.838,8.733,931108,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" -vectors,10000,json,1460530,1.0,0.035592,0.015402,0.039156,0.005009,0.074748,41.035,37.3,5180650,True,True,True,0.0,0.0,"compact text, lossless" -vectors,10000,json_zip,552940,2.641,0.06153,0.014493,0.042894,0.004846,0.104424,8.987,12.891,5183107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" -vectors,10000,compas_pb,800015,1.826,0.034889,0.00032,0.052195,0.002942,0.087084,22.93,15.327,2718665,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" -vectors,10000,compas_pb_zip,258630,5.647,0.039753,0.000354,0.051404,0.000822,0.091157,6.506,5.031,3519908,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" -vectors,10000,compas_pb_zstd,249995,5.842,0.036802,0.001163,0.050101,0.003043,0.086903,6.793,4.99,3518713,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" -vectors,10000,compas_msgpack,1060003,1.378,0.016814,0.014722,0.055728,0.004335,0.072542,63.043,19.021,8467704,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) -vectors,10000,compas_msgpack_zstd,507001,2.881,0.026296,0.014114,0.059855,0.003598,0.086151,19.281,8.47,9527740,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +arcs,1000,json,268295,1.0,0.007072,0.001601,0.037603,0.001039,0.044675,37.937,7.135,1622088,True,True,True,0.0,0.0,"compact text, lossless" +arcs,1000,json_zip,68511,3.916,0.009712,0.00161,0.038131,0.001092,0.047844,7.054,1.797,1624593,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +arcs,1000,compas_pb,181015,1.482,0.032803,0.008157,0.06335,0.003103,0.096153,5.518,2.857,1252237,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +arcs,1000,compas_pb_zip,63754,4.208,0.032968,0.000406,0.06318,0.002891,0.096148,1.934,1.009,1435212,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +arcs,1000,compas_pb_zstd,62213,4.313,0.033627,0.000794,0.06365,0.000251,0.097277,1.85,0.977,1433285,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +arcs,1000,compas_msgpack,241003,1.113,0.003316,0.001359,0.044791,0.000497,0.048107,72.668,5.381,2576504,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +arcs,1000,compas_msgpack_zstd,62528,4.291,0.005786,0.00155,0.04521,0.000327,0.050996,10.807,1.383,2819540,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +arcs,10000,json,2682697,1.0,0.06909,0.013955,0.402759,0.018057,0.471849,38.829,6.661,16245194,True,True,True,0.0,0.0,"compact text, lossless" +arcs,10000,json_zip,679255,3.949,0.100079,0.016797,0.402107,0.002985,0.502186,6.787,1.689,16247691,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +arcs,10000,compas_pb,1810015,1.482,0.318927,0.004797,0.657038,0.009109,0.975965,5.675,2.755,12560997,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +arcs,10000,compas_pb_zip,633338,4.236,0.339423,0.000702,0.680903,0.005152,1.020326,1.866,0.93,14372236,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +arcs,10000,compas_pb_zstd,608072,4.412,0.333858,0.001002,0.662761,0.007109,0.996619,1.821,0.917,14371045,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +arcs,10000,compas_msgpack,2410003,1.113,0.034504,0.018966,0.494853,0.010885,0.529357,69.847,4.87,25961704,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +arcs,10000,compas_msgpack_zstd,612369,4.381,0.050214,0.015306,0.49521,0.007832,0.545424,12.195,1.237,28371740,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +beziers,1000,json,333223,1.0,0.008323,0.001614,0.009469,0.002852,0.017792,40.038,35.19,1769015,True,True,True,0.0,0.0,"compact text, lossless" +beziers,1000,json_zip,145163,2.296,0.016482,0.001769,0.010035,0.002901,0.026517,8.808,14.465,1772232,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +beziers,1000,compas_pb,155015,2.15,0.004874,4.7e-05,0.010127,0.000334,0.015,31.807,15.307,1334757,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +beziers,1000,compas_pb_zip,93529,3.563,0.007238,0.000105,0.010534,0.000114,0.017772,12.922,8.879,1490728,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +beziers,1000,compas_pb_zstd,92304,3.61,0.005899,0.000517,0.010818,0.000311,0.016717,15.647,8.532,1489533,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +beziers,1000,compas_msgpack,199003,1.674,0.00322,0.001409,0.016516,0.000139,0.019735,61.807,12.049,2458003,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +beziers,1000,compas_msgpack_zstd,128882,2.585,0.00528,0.00146,0.016728,0.000119,0.022008,24.411,7.705,2658967,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +beziers,10000,json,3332149,1.0,0.084983,0.014918,0.120147,0.012173,0.205129,39.21,27.734,17768533,True,True,True,0.0,0.0,"compact text, lossless" +beziers,10000,json_zip,1443341,2.309,0.162021,0.016357,0.119257,0.012774,0.281278,8.908,12.103,17771038,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +beziers,10000,compas_pb,1550015,2.15,0.048604,0.000389,0.122811,0.010003,0.171415,31.891,12.621,13435077,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +beziers,10000,compas_pb_zip,933499,3.57,0.074076,0.000487,0.127033,0.003009,0.201109,12.602,7.349,14986264,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +beziers,10000,compas_pb_zstd,926258,3.597,0.061479,0.000201,0.119686,0.0093,0.181165,15.066,7.739,14985125,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +beziers,10000,compas_msgpack,1990003,1.674,0.030832,0.013972,0.193121,0.009705,0.223953,64.544,10.304,24790043,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +beziers,10000,compas_msgpack_zstd,1291146,2.581,0.0561,0.011494,0.209574,0.006214,0.265674,23.015,6.161,26780079,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +boxes,1000,json,285582,1.0,0.007341,0.001761,0.038356,0.000298,0.045698,38.902,7.445,1727304,True,True,True,0.0,0.0,"compact text, lossless" +boxes,1000,json_zip,89885,3.177,0.011682,0.001705,0.038718,0.000158,0.050399,7.695,2.322,1730025,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +boxes,1000,compas_pb,131015,2.18,0.006588,8.1e-05,0.044339,0.000373,0.050927,19.887,2.955,1339834,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +boxes,1000,compas_pb_zip,52308,5.46,0.008009,9.3e-05,0.044539,0.000199,0.052548,6.531,1.174,1472077,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,1000,compas_pb_zstd,50046,5.706,0.007557,8.7e-05,0.044484,0.002718,0.052041,6.622,1.125,1470882,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +boxes,1000,compas_msgpack,230003,1.242,0.003551,0.001478,0.046745,0.003604,0.050296,64.774,4.92,2664336,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +boxes,1000,compas_msgpack_zstd,79414,3.596,0.005589,0.001513,0.046811,0.003166,0.0524,14.208,1.696,2894372,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +boxes,10000,json,2855355,1.0,0.076544,0.016254,0.411353,0.005062,0.487897,37.304,6.941,17297613,True,True,True,0.0,0.0,"compact text, lossless" +boxes,10000,json_zip,892076,3.201,0.118517,0.019871,0.407826,0.00325,0.526343,7.527,2.187,17300118,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +boxes,10000,compas_pb,1310015,2.18,0.069365,0.001126,0.474763,0.011035,0.544128,18.886,2.759,13440386,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +boxes,10000,compas_pb_zip,520863,5.482,0.083471,0.001417,0.473279,0.00942,0.55675,6.24,1.101,14751629,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +boxes,10000,compas_pb_zstd,497195,5.743,0.078139,0.000662,0.467836,0.011656,0.545975,6.363,1.063,14750434,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +boxes,10000,compas_msgpack,2300003,1.241,0.040141,0.022583,0.505184,0.01458,0.545325,57.299,4.553,26841536,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +boxes,10000,compas_msgpack_zstd,795250,3.591,0.062097,0.016176,0.514242,0.002361,0.576339,12.807,1.546,29141572,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +capsules,1000,json,265867,1.0,0.006876,0.001691,0.037796,0.003298,0.044672,38.665,7.034,1683597,True,True,True,0.0,0.0,"compact text, lossless" +capsules,1000,json_zip,79063,3.363,0.010533,0.001689,0.041099,0.001383,0.051632,7.506,1.924,1686318,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +capsules,1000,compas_pb,125015,2.127,0.006688,0.000141,0.044626,0.000229,0.051314,18.693,2.801,1315830,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +capsules,1000,compas_pb_zip,43554,6.104,0.007906,0.000146,0.04462,0.000722,0.052526,5.509,0.976,1442073,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +capsules,1000,compas_pb_zstd,41512,6.405,0.007472,5.4e-05,0.044039,0.003082,0.051512,5.555,0.943,1440878,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +capsules,1000,compas_msgpack,221003,1.203,0.003272,0.001489,0.045112,0.003454,0.048385,67.536,4.899,2644332,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +capsules,1000,compas_msgpack_zstd,70876,3.751,0.005168,0.001557,0.0464,0.002405,0.051568,13.715,1.528,2865368,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +capsules,10000,json,2658207,1.0,0.073385,0.016586,0.420879,0.003567,0.494264,36.223,6.316,16860473,True,True,True,0.0,0.0,"compact text, lossless" +capsules,10000,json_zip,783424,3.393,0.114558,0.015898,0.413156,0.001282,0.527714,6.839,1.896,16862970,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +capsules,10000,compas_pb,1250015,2.127,0.065869,0.000484,0.463899,0.014596,0.529768,18.977,2.695,13200310,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +capsules,10000,compas_pb_zip,432880,6.141,0.081678,0.003014,0.46722,0.003746,0.548898,5.3,0.927,14451553,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +capsules,10000,compas_pb_zstd,417417,6.368,0.074973,0.00153,0.474298,0.006369,0.549272,5.568,0.88,14450422,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +capsules,10000,compas_msgpack,2210003,1.203,0.034165,0.020661,0.493644,0.010509,0.527809,64.686,4.477,26641972,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +capsules,10000,compas_msgpack_zstd,694999,3.825,0.0503,0.015698,0.479676,0.014363,0.529976,13.817,1.449,28852008,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +circles,1000,json,237208,1.0,0.006558,0.001674,0.038055,0.004218,0.044613,36.169,6.233,1542921,True,True,True,0.0,0.0,"compact text, lossless" +circles,1000,json_zip,68265,3.475,0.009145,0.001783,0.037922,0.000341,0.047068,7.464,1.8,1545754,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +circles,1000,compas_pb,163015,1.455,0.007787,0.001554,0.045423,0.000271,0.05321,20.934,3.589,1358721,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +circles,1000,compas_pb_zip,63549,3.733,0.009898,0.001823,0.046496,0.000609,0.056394,6.42,1.367,1522964,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +circles,1000,compas_pb_zstd,61971,3.828,0.009818,0.001825,0.046846,0.002909,0.056664,6.312,1.323,1521769,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +circles,1000,compas_msgpack,204003,1.163,0.003292,0.001948,0.047407,0.003455,0.050699,61.973,4.303,2531491,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +circles,1000,compas_msgpack_zstd,62189,3.814,0.004729,0.001533,0.045716,0.003974,0.050444,13.152,1.36,2735527,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +circles,10000,json,2372279,1.0,0.070734,0.016622,0.414811,0.005502,0.485545,33.538,5.719,15454648,True,True,True,0.0,0.0,"compact text, lossless" +circles,10000,json_zip,677454,3.502,0.103476,0.014396,0.404193,0.004958,0.507669,6.547,1.676,15457153,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +circles,10000,compas_pb,1630015,1.455,0.076059,0.020065,0.468363,0.006421,0.544423,21.431,3.48,13630497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +circles,10000,compas_pb_zip,631596,3.756,0.102093,0.016691,0.494134,0.006834,0.596227,6.186,1.278,15261680,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +circles,10000,compas_pb_zstd,606491,3.911,0.096631,0.017451,0.489836,0.004357,0.586467,6.276,1.238,15260545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +circles,10000,compas_msgpack,2040003,1.163,0.03274,0.020971,0.482244,0.011799,0.514984,62.31,4.23,25511619,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +circles,10000,compas_msgpack_zstd,608912,3.896,0.046048,0.015777,0.481973,0.009111,0.528022,13.223,1.263,27552103,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +cones,1000,json,262665,1.0,0.006816,0.001683,0.03774,0.002815,0.044556,38.535,6.96,1680389,True,True,True,0.0,0.0,"compact text, lossless" +cones,1000,json_zip,79124,3.32,0.010148,0.001628,0.037995,0.000208,0.048143,7.797,2.082,1683110,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +cones,1000,compas_pb,122015,2.153,0.006401,4.1e-05,0.043615,4.1e-05,0.050017,19.061,2.798,1315827,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +cones,1000,compas_pb_zip,43545,6.032,0.007707,0.000113,0.04375,0.00028,0.051457,5.65,0.995,1439070,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +cones,1000,compas_pb_zstd,41447,6.337,0.007281,7.5e-05,0.045233,0.002842,0.052514,5.692,0.916,1437875,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +cones,1000,compas_msgpack,218003,1.205,0.003601,0.001784,0.047207,0.003494,0.050808,60.531,4.618,2641329,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +cones,1000,compas_msgpack_zstd,70775,3.711,0.005089,0.001482,0.04608,0.003579,0.051169,13.908,1.536,2859365,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +cones,10000,json,2626398,1.0,0.075925,0.014214,0.42654,0.000324,0.502466,34.592,6.157,16828658,True,True,True,0.0,0.0,"compact text, lossless" +cones,10000,json_zip,783565,3.352,0.112422,0.014151,0.424958,0.010583,0.53738,6.97,1.844,16831163,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +cones,10000,compas_pb,1220015,2.153,0.065352,0.002205,0.466013,0.002961,0.531365,18.668,2.618,13200307,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +cones,10000,compas_pb_zip,432919,6.067,0.085035,0.002992,0.469355,0.005154,0.55439,5.091,0.922,14421550,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +cones,10000,compas_pb_zstd,411478,6.383,0.073986,0.000472,0.457814,0.004021,0.531801,5.562,0.899,14420419,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +cones,10000,compas_msgpack,2180003,1.205,0.034727,0.020199,0.501323,0.01574,0.53605,62.775,4.349,26611969,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +cones,10000,compas_msgpack_zstd,694716,3.781,0.052253,0.014524,0.480199,0.013182,0.532452,13.295,1.447,28792005,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +cylinders,1000,json,266665,1.0,0.006902,0.001666,0.037649,0.002927,0.04455,38.638,7.083,1684445,True,True,True,0.0,0.0,"compact text, lossless" +cylinders,1000,json_zip,79314,3.362,0.010201,0.00175,0.037858,4.4e-05,0.048059,7.775,2.095,1687118,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +cylinders,1000,compas_pb,126015,2.116,0.006493,4.8e-05,0.0435,0.00011,0.049994,19.407,2.897,1315831,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +cylinders,1000,compas_pb_zip,43566,6.121,0.007859,9.6e-05,0.04373,0.000135,0.051588,5.544,0.996,1443074,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +cylinders,1000,compas_pb_zstd,41449,6.434,0.00734,3e-05,0.043569,0.002941,0.050909,5.647,0.951,1441879,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +cylinders,1000,compas_msgpack,222003,1.201,0.00327,0.001479,0.044762,0.002796,0.048032,67.89,4.96,2645797,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +cylinders,1000,compas_msgpack_zstd,70805,3.766,0.005812,0.002098,0.044822,0.003094,0.050634,12.183,1.58,2867369,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +cylinders,10000,json,2666398,1.0,0.071329,0.015927,0.40873,0.002746,0.480058,37.382,6.524,16868666,True,True,True,0.0,0.0,"compact text, lossless" +cylinders,10000,json_zip,786031,3.392,0.109883,0.015195,0.402528,0.014526,0.51241,7.153,1.953,16871163,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +cylinders,10000,compas_pb,1260015,2.116,0.065593,0.001913,0.450207,0.00894,0.5158,19.21,2.799,13200311,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +cylinders,10000,compas_pb_zip,433106,6.156,0.080402,0.003484,0.458553,0.002426,0.538956,5.387,0.945,14461554,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +cylinders,10000,compas_pb_zstd,411480,6.48,0.074573,0.000287,0.465846,0.011668,0.540419,5.518,0.883,14460423,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +cylinders,10000,compas_msgpack,2220003,1.201,0.034447,0.019473,0.493865,0.010036,0.528312,64.447,4.495,26651973,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +cylinders,10000,compas_msgpack_zstd,694866,3.837,0.048995,0.016518,0.476476,0.00989,0.525471,14.182,1.458,28872009,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +ellipses,1000,json,263769,1.0,0.006955,0.001637,0.037916,0.000135,0.044872,37.923,6.957,1593497,True,True,True,0.0,0.0,"compact text, lossless" +ellipses,1000,json_zip,78973,3.34,0.010288,0.001733,0.038186,0.000163,0.048474,7.676,2.068,1596386,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +ellipses,1000,compas_pb,125015,2.11,0.006517,9.5e-05,0.043571,0.000699,0.050088,19.183,2.869,1227830,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +ellipses,1000,compas_pb_zip,43449,6.071,0.007918,6.2e-05,0.04435,0.000326,0.052268,5.487,0.98,1354073,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +ellipses,1000,compas_pb_zstd,41980,6.283,0.007513,8.6e-05,0.044617,0.003093,0.05213,5.588,0.941,1352878,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +ellipses,1000,compas_msgpack,219003,1.204,0.003235,0.00147,0.044901,0.002974,0.048136,67.694,4.877,2556964,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +ellipses,1000,compas_msgpack_zstd,71246,3.702,0.005065,0.001499,0.045055,0.003201,0.05012,14.067,1.581,2775536,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +ellipses,10000,json,2637716,1.0,0.072704,0.016355,0.405453,0.004975,0.478157,36.28,6.506,15960148,True,True,True,0.0,0.0,"compact text, lossless" +ellipses,10000,json_zip,782835,3.369,0.103335,0.015722,0.415888,0.002496,0.519223,7.576,1.882,15962653,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +ellipses,10000,compas_pb,1250015,2.11,0.066399,0.000578,0.45164,0.003774,0.518039,18.826,2.768,12320478,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +ellipses,10000,compas_pb_zip,431885,6.107,0.079459,0.0003,0.456206,0.006915,0.535665,5.435,0.947,13571717,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +ellipses,10000,compas_pb_zstd,422121,6.249,0.074811,0.000873,0.452206,0.003897,0.527017,5.642,0.933,13570590,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +ellipses,10000,compas_msgpack,2190003,1.204,0.033456,0.020116,0.49041,0.010259,0.523867,65.459,4.466,25762140,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +ellipses,10000,compas_msgpack_zstd,697824,3.78,0.052847,0.016515,0.495572,0.013921,0.548419,13.205,1.408,27952176,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +frames,1000,json,295873,1.0,0.006981,0.001598,0.019399,5.2e-05,0.02638,42.384,15.252,1384557,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"compact text, lossless" +frames,1000,json_zip,109718,2.697,0.013239,0.001569,0.019925,0.000139,0.033165,8.287,5.506,1386838,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"zip-compressed json, size baseline" +frames,1000,compas_pb,141015,2.098,0.005426,4e-05,0.024984,0.002441,0.03041,25.991,5.644,987572,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, double + flat arrays (optimized)" +frames,1000,compas_pb_zip,71467,4.14,0.008023,6.1e-05,0.026358,0.000626,0.034381,8.907,2.711,1129815,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zip-compressed" +frames,1000,compas_pb_zstd,69763,4.241,0.00655,5.6e-05,0.025058,5e-05,0.031608,10.651,2.784,1128620,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"protobuf binary, zstandard-compressed" +frames,1000,compas_msgpack,180003,1.644,0.00288,0.00142,0.024207,0.002951,0.027087,62.5,7.436,2081068,False,False,False,4.440892098500626e-16,6.299702658387308e-17,msgpack over the JSON-shape tree (Kumiki-style) +frames,1000,compas_msgpack_zstd,96681,3.06,0.004742,0.001417,0.024717,0.002799,0.029459,20.389,3.911,2261104,False,False,False,4.440892098500626e-16,6.299702658387308e-17,"msgpack, zstandard-compressed" +frames,10000,json,2959373,1.0,0.071039,0.015743,0.209222,0.001677,0.280261,41.658,14.145,13880377,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"compact text, lossless" +frames,10000,json_zip,1090015,2.715,0.13423,0.016016,0.20977,0.00244,0.344,8.121,5.196,13882874,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"zip-compressed json, size baseline" +frames,10000,compas_pb,1410015,2.099,0.054856,0.000448,0.261003,0.004887,0.315859,25.704,5.402,9920052,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, double + flat arrays (optimized)" +frames,10000,compas_pb_zip,712585,4.153,0.084688,0.000907,0.269609,0.00394,0.354297,8.414,2.643,11331295,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zip-compressed" +frames,10000,compas_pb_zstd,707041,4.186,0.065067,0.000351,0.257587,0.005743,0.322653,10.866,2.745,11330100,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"protobuf binary, zstandard-compressed" +frames,10000,compas_msgpack,1800003,1.644,0.028352,0.014985,0.261971,0.007099,0.290323,63.488,6.871,21017740,False,False,False,5.551115123125783e-16,6.326276205293956e-17,msgpack over the JSON-shape tree (Kumiki-style) +frames,10000,compas_msgpack_zstd,964301,3.069,0.044745,0.016365,0.263631,0.009394,0.308377,21.551,3.658,22817776,False,False,False,5.551115123125783e-16,6.326276205293956e-17,"msgpack, zstandard-compressed" +graph,1000,json,76719,1.0,0.001584,6.2e-05,0.011425,4e-05,0.013009,48.43,6.715,1938217,True,True,True,0.0,0.0,"compact text, lossless" +graph,1000,json_zip,24330,3.153,0.0032,5.7e-05,0.011572,4e-05,0.014771,7.604,2.103,1940018,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +graph,1000,compas_pb,37178,2.064,0.004064,8.6e-05,0.003736,3e-05,0.0078,9.148,9.951,1115572,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +graph,1000,compas_pb_zip,15463,4.961,0.00461,5.1e-05,0.003799,2.4e-05,0.008409,3.354,4.07,1154146,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +graph,1000,compas_pb_zstd,16070,4.774,0.004289,3.8e-05,0.003817,9.1e-05,0.008106,3.747,4.21,1152783,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +graph,1000,compas_msgpack,53875,1.424,0.000578,1.2e-05,0.014344,5.7e-05,0.014923,93.156,3.756,2544105,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +graph,1000,compas_msgpack_zstd,17743,4.324,0.001185,5.8e-05,0.014861,0.003225,0.016046,14.974,1.194,2614349,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +graph,10000,json,793664,1.0,0.016792,0.00022,0.130168,0.004248,0.14696,47.264,6.097,19057914,True,True,True,0.0,0.0,"compact text, lossless" +graph,10000,json_zip,213388,3.719,0.032723,0.003155,0.128133,0.005875,0.160856,6.521,1.665,19020680,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +graph,10000,compas_pb,368817,2.152,0.041263,0.001057,0.038277,0.005361,0.07954,8.938,9.635,11049444,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +graph,10000,compas_pb_zip,142716,5.561,0.04853,0.000927,0.038508,0.005182,0.087038,2.941,3.706,11419653,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +graph,10000,compas_pb_zstd,185816,4.271,0.041129,0.000623,0.036771,0.005013,0.0779,4.518,5.053,11418294,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +graph,10000,compas_msgpack,564802,1.405,0.006052,6.8e-05,0.160978,0.002158,0.16703,93.318,3.509,25139034,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +graph,10000,compas_msgpack_zstd,118950,6.672,0.010278,0.000479,0.160419,0.002941,0.170697,11.573,0.741,25684514,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +hyperbolas,1000,json,265769,1.0,0.006847,0.001634,0.037902,0.000299,0.044748,38.818,7.012,1595501,True,True,True,0.0,0.0,"compact text, lossless" +hyperbolas,1000,json_zip,79190,3.356,0.010663,0.001848,0.038909,0.000183,0.049572,7.427,2.035,1598006,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +hyperbolas,1000,compas_pb,127015,2.092,0.006613,0.000105,0.044604,0.002902,0.051217,19.207,2.848,1227832,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +hyperbolas,1000,compas_pb_zip,43453,6.116,0.007873,7.4e-05,0.044699,0.000202,0.052571,5.519,0.972,1356399,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +hyperbolas,1000,compas_pb_zstd,41986,6.33,0.007738,0.000152,0.044744,0.000261,0.052482,5.426,0.938,1354880,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +hyperbolas,1000,compas_msgpack,221003,1.203,0.00342,0.001462,0.045479,0.00015,0.048899,64.612,4.859,2558502,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +hyperbolas,1000,compas_msgpack_zstd,71166,3.734,0.005167,0.001678,0.044211,0.000424,0.049378,13.774,1.61,2779538,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +hyperbolas,10000,json,2657716,1.0,0.069272,0.01608,0.403566,0.00719,0.472838,38.366,6.586,15980152,True,True,True,0.0,0.0,"compact text, lossless" +hyperbolas,10000,json_zip,784701,3.387,0.107953,0.016108,0.409325,0.007833,0.517278,7.269,1.917,15982649,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +hyperbolas,10000,compas_pb,1270015,2.093,0.067892,0.000665,0.479525,0.010676,0.547417,18.706,2.648,12320480,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +hyperbolas,10000,compas_pb_zip,431927,6.153,0.080055,0.000817,0.478074,0.018894,0.558129,5.395,0.903,13591723,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +hyperbolas,10000,compas_pb_zstd,416781,6.377,0.074741,0.001143,0.476262,0.005931,0.551003,5.576,0.875,13590592,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +hyperbolas,10000,compas_msgpack,2210003,1.203,0.033095,0.019524,0.51026,0.017266,0.543355,66.778,4.331,25782142,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +hyperbolas,10000,compas_msgpack_zstd,697597,3.81,0.048336,0.016598,0.491277,0.01781,0.539613,14.432,1.42,27992178,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +lines,1000,json,218115,1.0,0.007567,0.001605,0.007851,6.4e-05,0.015419,28.823,27.78,1042065,True,True,True,0.0,0.0,"compact text, lossless" +lines,1000,json_zip,86982,2.508,0.011967,0.001801,0.008677,5.5e-05,0.020644,7.268,10.025,1044570,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +lines,1000,compas_pb,109015,2.001,0.007204,0.000149,0.012376,0.000149,0.019579,15.133,8.809,722835,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +lines,1000,compas_pb_zip,51798,4.211,0.00891,4.7e-05,0.011775,0.000107,0.020685,5.814,4.399,833078,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +lines,1000,compas_pb_zstd,50170,4.348,0.007831,3.2e-05,0.011658,5.3e-05,0.019489,6.407,4.303,831883,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +lines,1000,compas_msgpack,143003,1.525,0.004604,0.001481,0.011669,0.002841,0.016273,31.063,12.255,1663713,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +lines,1000,compas_msgpack_zstd,78584,2.776,0.006365,0.001619,0.012084,9.9e-05,0.01845,12.345,6.503,1807901,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +lines,10000,json,2181230,1.0,0.079018,0.017773,0.098675,0.004451,0.177693,27.604,22.105,10461548,True,True,True,0.0,0.0,"compact text, lossless" +lines,10000,json_zip,862805,2.528,0.126112,0.022179,0.094439,0.001901,0.220551,6.842,9.136,10464765,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +lines,10000,compas_pb,1090015,2.001,0.071602,0.000813,0.123461,0.004798,0.195062,15.223,8.829,7279619,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +lines,10000,compas_pb_zip,515699,4.23,0.088517,0.000505,0.123776,0.005476,0.212293,5.826,4.166,8370862,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +lines,10000,compas_pb_zstd,498282,4.378,0.07815,0.000828,0.122706,0.004395,0.200856,6.376,4.061,8369667,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +lines,10000,compas_msgpack,1430003,1.525,0.04662,0.019045,0.126266,0.000998,0.172886,30.673,11.325,16848977,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +lines,10000,compas_msgpack_zstd,769242,2.836,0.061128,0.017857,0.133847,0.005272,0.194975,12.584,5.747,18277541,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh,1000,json,82154,1.0,0.001537,5.8e-05,0.003897,0.00014,0.005434,53.452,21.08,1611855,True,True,True,0.0,0.0,"compact text, lossless" +mesh,1000,json_zip,28055,2.928,0.003593,0.000104,0.004012,3.7e-05,0.007605,7.807,6.993,1614520,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,1000,compas_pb,32913,2.496,0.001696,9.1e-05,0.003311,0.000118,0.005007,19.404,9.94,878003,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,1000,compas_pb_zip,16331,5.031,0.002344,0.00014,0.003564,0.003229,0.005908,6.968,4.582,912308,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,1000,compas_pb_zstd,16203,5.07,0.002037,4.2e-05,0.003362,7.5e-05,0.005399,7.955,4.819,910949,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh,1000,compas_msgpack,58668,1.4,0.000417,2.3e-05,0.008012,0.000163,0.008429,140.775,7.322,2063130,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh,1000,compas_msgpack_zstd,25136,3.268,0.001021,6.1e-05,0.008059,0.000218,0.00908,24.623,3.119,2121831,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh,10000,json,884888,1.0,0.017384,0.000509,0.045684,0.001255,0.063069,50.901,19.37,16027677,True,True,True,0.0,0.0,"compact text, lossless" +mesh,10000,json_zip,243860,3.629,0.041425,0.00342,0.047223,0.004057,0.088648,5.887,5.164,16030462,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh,10000,compas_pb,328024,2.698,0.017853,0.000293,0.034453,0.00408,0.052306,18.374,9.521,8717491,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh,10000,compas_pb_zip,162262,5.453,0.024709,0.000499,0.035179,0.003829,0.059887,6.567,4.613,9048007,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh,10000,compas_pb_zstd,172651,5.125,0.022036,0.000193,0.043727,0.005014,0.065763,7.835,3.948,9045548,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh,10000,compas_msgpack,621054,1.425,0.004179,7.9e-05,0.084139,0.002519,0.088318,148.612,7.381,20581152,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh,10000,compas_msgpack_zstd,203524,4.348,0.008292,0.0003,0.086607,0.004259,0.094899,24.544,2.35,21202239,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh_attrs,1000,json,112098,1.0,0.001868,2.6e-05,0.003812,0.00247,0.005679,60.026,29.41,1666239,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,1000,json_zip,38109,2.942,0.0044,0.000105,0.003898,5.6e-05,0.008298,8.661,9.777,1669104,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,1000,compas_pb,41120,2.726,0.00198,0.000212,0.00363,0.000133,0.00561,20.766,11.329,967891,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,1000,compas_pb_zip,24312,4.611,0.002601,0.000104,0.003488,3.4e-05,0.00609,9.346,6.969,1010407,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,1000,compas_pb_zstd,24277,4.617,0.002293,1.8e-05,0.003408,1.9e-05,0.005701,10.588,7.123,1009044,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh_attrs,1000,compas_msgpack,76076,1.474,0.00043,1.8e-05,0.007945,8.2e-05,0.008375,177.11,9.575,2088138,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh_attrs,1000,compas_msgpack_zstd,33793,3.317,0.001242,4.3e-05,0.00797,5.1e-05,0.009212,27.209,4.24,2164031,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +mesh_attrs,10000,json,1177508,1.0,0.019435,0.003109,0.046367,0.004595,0.065801,60.588,25.396,16560353,True,True,True,0.0,0.0,"compact text, lossless" +mesh_attrs,10000,json_zip,347072,3.393,0.050652,0.002629,0.047049,0.004257,0.097701,6.852,7.377,16563314,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +mesh_attrs,10000,compas_pb,408041,2.886,0.019791,0.000243,0.034531,0.004228,0.054323,20.617,11.817,9597267,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +mesh_attrs,10000,compas_pb_zip,238533,4.936,0.028828,0.003088,0.035876,0.005185,0.064704,8.274,6.649,10007508,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +mesh_attrs,10000,compas_pb_zstd,238887,4.929,0.02214,0.000196,0.039623,0.003671,0.061763,10.79,6.029,10005341,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +mesh_attrs,10000,compas_msgpack,791054,1.489,0.004613,0.000268,0.098854,0.00428,0.103467,171.476,8.002,20820088,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +mesh_attrs,10000,compas_msgpack_zstd,282069,4.175,0.00991,3.7e-05,0.090372,0.00207,0.100282,28.463,3.121,21610719,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +parabolas,1000,json,238538,1.0,0.007003,0.00163,0.039192,0.003178,0.046195,34.062,6.086,1544206,True,True,True,0.0,0.0,"compact text, lossless" +parabolas,1000,json_zip,68248,3.495,0.009138,0.001606,0.040282,0.00409,0.04942,7.469,1.694,1547471,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +parabolas,1000,compas_pb,117015,2.039,0.006925,0.000199,0.044954,0.000142,0.051879,16.898,2.603,1203823,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +parabolas,1000,compas_pb_zip,35047,6.806,0.007979,0.000195,0.046038,0.000971,0.054018,4.392,0.761,1322062,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +parabolas,1000,compas_pb_zstd,33413,7.139,0.007189,7.4e-05,0.045248,0.002487,0.052437,4.648,0.738,1320871,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +parabolas,1000,compas_msgpack,205003,1.164,0.003458,0.001547,0.047421,0.003151,0.050879,59.282,4.323,2533493,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +parabolas,1000,compas_msgpack_zstd,62269,3.831,0.005308,0.001663,0.045565,0.003813,0.050873,11.732,1.367,2738993,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +parabolas,10000,json,2385128,1.0,0.070854,0.013557,0.40854,0.004681,0.479394,33.663,5.838,15467500,True,True,True,0.0,0.0,"compact text, lossless" +parabolas,10000,json_zip,676861,3.524,0.101085,0.013715,0.403541,0.005187,0.504626,6.696,1.677,15470005,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +parabolas,10000,compas_pb,1170015,2.039,0.064002,0.000756,0.446724,0.019448,0.510726,18.281,2.619,12080599,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +parabolas,10000,compas_pb_zip,347980,6.854,0.076052,0.001029,0.466687,0.006351,0.542739,4.576,0.746,13251842,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +parabolas,10000,compas_pb_zstd,332702,7.169,0.074816,0.001657,0.45273,0.001267,0.527545,4.447,0.735,13250647,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +parabolas,10000,compas_msgpack,2050003,1.163,0.034597,0.014856,0.485892,0.00843,0.520489,59.253,4.219,25531621,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +parabolas,10000,compas_msgpack_zstd,622158,3.834,0.0487,0.01523,0.467736,0.012402,0.516436,12.775,1.33,27582105,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +planes,1000,json,225141,1.0,0.005392,0.001506,0.008119,0.000117,0.013511,41.757,27.729,1048924,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"compact text, lossless" +planes,1000,json_zip,87404,2.576,0.009632,0.001543,0.0088,0.000297,0.018433,9.074,9.932,1051621,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"zip-compressed json, size baseline" +planes,1000,compas_pb,110015,2.046,0.004615,3.4e-05,0.012188,8.1e-05,0.016802,23.84,9.027,722652,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, double + flat arrays (optimized)" +planes,1000,compas_pb_zip,52297,4.305,0.00611,4.6e-05,0.012936,0.002525,0.019046,8.559,4.043,834631,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zip-compressed" +planes,1000,compas_pb_zstd,50611,4.448,0.006062,0.000386,0.01277,0.000107,0.018832,8.349,3.963,832700,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"protobuf binary, zstandard-compressed" +planes,1000,compas_msgpack,147003,1.532,0.00237,0.00143,0.012,0.002758,0.01437,62.031,12.25,1664479,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,msgpack over the JSON-shape tree (Kumiki-style) +planes,1000,compas_msgpack_zstd,79405,2.835,0.003914,0.001424,0.011789,7.2e-05,0.015703,20.288,6.735,1811515,False,False,False,2.220446049250313e-16,3.8070810520916334e-17,"msgpack, zstandard-compressed" +planes,10000,json,2251968,1.0,0.054829,0.01491,0.08804,0.00505,0.142869,41.073,25.579,10532543,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"compact text, lossless" +planes,10000,json_zip,866592,2.599,0.107731,0.012808,0.094277,0.005338,0.202008,8.044,9.192,10535048,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"zip-compressed json, size baseline" +planes,10000,compas_pb,1100015,2.047,0.046513,0.00043,0.127926,0.002622,0.174439,23.65,8.599,7279204,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, double + flat arrays (optimized)" +planes,10000,compas_pb_zip,520659,4.325,0.064084,0.001044,0.132305,0.007231,0.196389,8.125,3.935,8380447,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zip-compressed" +planes,10000,compas_pb_zstd,508937,4.425,0.056098,0.000865,0.121982,0.005046,0.17808,9.072,4.172,8379436,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"protobuf binary, zstandard-compressed" +planes,10000,compas_msgpack,1470003,1.532,0.023864,0.014224,0.130024,0.002159,0.153888,61.598,11.306,16858631,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,msgpack over the JSON-shape tree (Kumiki-style) +planes,10000,compas_msgpack_zstd,780214,2.886,0.036904,0.014364,0.131939,0.002809,0.168843,21.142,5.913,18327187,False,False,False,2.220446049250313e-16,3.6521254613811506e-17,"msgpack, zstandard-compressed" +pointcloud,10000,json,580633,1.0,0.013698,0.002552,0.013345,0.002919,0.027043,42.389,43.509,4261534,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,10000,json_zip,280723,2.068,0.033178,0.00016,0.014419,0.002546,0.047597,8.461,19.469,4264087,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,10000,compas_pb,240074,2.419,0.003156,5.4e-05,0.010464,0.003095,0.01362,76.074,22.943,3599350,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,10000,compas_pb_zip,228795,2.538,0.009099,5.6e-05,0.011176,0.002753,0.020275,25.144,20.472,3840652,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,10000,compas_pb_zstd,227771,2.549,0.003261,2.6e-05,0.010694,0.00257,0.013955,69.851,21.298,3839561,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +pointcloud,10000,compas_msgpack,280093,2.073,0.003679,0.000157,0.027085,0.002853,0.030764,76.134,10.341,4564763,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +pointcloud,10000,compas_msgpack_zstd,250823,2.315,0.004578,4e-05,0.027124,0.002704,0.031702,54.79,9.247,4844889,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +pointcloud,100000,json,5804860,1.0,0.145928,0.000854,0.188759,0.017318,0.334687,39.779,30.753,42597425,True,True,True,0.0,0.0,"compact text, lossless" +pointcloud,100000,json_zip,2792749,2.079,0.347382,0.000747,0.187143,0.018634,0.534525,8.039,14.923,42599922,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +pointcloud,100000,compas_pb,2400078,2.419,0.031629,0.000233,0.155439,0.004145,0.187067,75.883,15.441,35996478,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +pointcloud,100000,compas_pb_zip,2286030,2.539,0.09374,0.001024,0.17182,0.005073,0.26556,24.387,13.305,38397656,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +pointcloud,100000,compas_pb_zstd,2276982,2.549,0.03346,0.000394,0.160496,0.003282,0.193956,68.052,14.187,38396589,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +pointcloud,100000,compas_msgpack,2800095,2.073,0.054778,0.00201,0.369046,0.014584,0.423825,51.117,7.587,45598691,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +pointcloud,100000,compas_msgpack_zstd,2457514,2.362,0.086833,0.001013,0.379253,0.010796,0.466086,28.302,6.48,48398587,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +points,1000,json,145071,1.0,0.003812,0.001454,0.003595,0.000105,0.007407,38.058,40.348,512768,True,True,True,0.0,0.0,"compact text, lossless" +points,1000,json_zip,55933,2.594,0.006212,0.00166,0.00409,0.000111,0.010302,9.005,13.675,515273,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +points,1000,compas_pb,79015,1.836,0.003504,8.6e-05,0.004862,4.7e-05,0.008366,22.55,16.252,266342,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +points,1000,compas_pb_zip,26095,5.559,0.003885,5.7e-05,0.005039,8.5e-05,0.008924,6.717,5.179,346581,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +points,1000,compas_pb_zstd,24960,5.812,0.003757,8.9e-05,0.004859,9e-05,0.008616,6.644,5.137,345390,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +points,1000,compas_msgpack,105003,1.382,0.001669,0.001447,0.005053,7.5e-05,0.006722,62.928,20.78,824034,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +points,1000,compas_msgpack_zstd,51854,2.798,0.003063,0.0014,0.005686,0.000144,0.008749,16.93,9.119,929070,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +points,10000,json,1450530,1.0,0.037264,0.016079,0.037692,0.004449,0.074957,38.926,38.483,5170931,True,True,True,0.0,0.0,"compact text, lossless" +points,10000,json_zip,552701,2.624,0.058725,0.013885,0.039046,0.003188,0.097772,9.412,14.155,5173436,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +points,10000,compas_pb,790015,1.836,0.032838,0.000466,0.048128,0.002703,0.080966,24.058,16.415,2718662,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +points,10000,compas_pb_zip,258617,5.609,0.039877,0.000396,0.049839,0.002962,0.089716,6.485,5.189,3509905,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +points,10000,compas_pb_zstd,247395,5.863,0.039714,0.00069,0.050445,0.000276,0.090158,6.229,4.904,3509238,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +points,10000,compas_msgpack,1050003,1.381,0.017006,0.013596,0.060668,0.003651,0.077674,61.744,17.307,8456186,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +points,10000,compas_msgpack_zstd,511567,2.835,0.02958,0.015838,0.064147,0.004647,0.093727,17.295,7.975,9506222,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polygons,1000,json,450157,1.0,0.011143,0.00165,0.018675,0.003044,0.029818,40.4,24.104,2558296,True,True,True,0.0,0.0,"compact text, lossless" +polygons,1000,json_zip,202604,2.222,0.022447,0.002063,0.018942,4.5e-05,0.041389,9.026,10.696,2561197,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polygons,1000,compas_pb,204015,2.206,0.005293,8.4e-05,0.018942,0.000165,0.024236,38.544,10.77,2007222,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polygons,1000,compas_pb_zip,139427,3.229,0.008754,8.9e-05,0.019054,0.003026,0.027809,15.926,7.317,2212361,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polygons,1000,compas_pb_zstd,138167,3.258,0.006619,6.2e-05,0.018784,0.002491,0.025403,20.873,7.356,2211166,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polygons,1000,compas_msgpack,256003,1.758,0.003701,0.001459,0.027738,0.002958,0.031438,69.179,9.229,3307428,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polygons,1000,compas_msgpack_zstd,178124,2.527,0.006507,0.001464,0.029499,0.002419,0.036006,27.375,6.038,3565336,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polygons,10000,json,4502991,1.0,0.111293,0.015627,0.207255,0.00968,0.318548,40.461,21.727,25659554,True,True,True,0.0,0.0,"compact text, lossless" +polygons,10000,json_zip,2016881,2.233,0.226688,0.020155,0.21226,0.003665,0.438948,8.897,9.502,25662051,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polygons,10000,compas_pb,2040015,2.207,0.053744,0.000441,0.210564,0.010189,0.264308,37.958,9.688,20155542,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polygons,10000,compas_pb_zip,1392267,3.234,0.091347,0.001646,0.220588,0.007129,0.311935,15.242,6.312,22196785,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polygons,10000,compas_pb_zstd,1377765,3.268,0.068386,0.001381,0.220798,0.010039,0.289184,20.147,6.24,22195590,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polygons,10000,compas_msgpack,2560003,1.759,0.037512,0.01451,0.34165,0.006615,0.379162,68.245,7.493,33279460,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polygons,10000,compas_msgpack_zstd,1793651,2.511,0.060262,0.014298,0.337003,0.004939,0.397265,29.764,5.322,35840616,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polyhedrons,1000,json,381223,1.0,0.007924,0.002093,0.006517,0.00025,0.014441,48.11,58.494,1840795,True,True,True,0.0,0.0,"compact text, lossless" +polyhedrons,1000,json_zip,146891,2.595,0.015351,0.003721,0.006969,0.002671,0.02232,9.569,21.079,1843292,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polyhedrons,1000,compas_pb,185015,2.06,0.007675,8.8e-05,0.008389,0.002621,0.016064,24.106,22.054,1294035,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polyhedrons,1000,compas_pb_zip,93696,4.069,0.009828,0.000172,0.008612,0.003009,0.01844,9.534,10.879,1480278,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polyhedrons,1000,compas_pb_zstd,92462,4.123,0.008597,6e-05,0.008283,0.003155,0.016881,10.755,11.162,1479083,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polyhedrons,1000,compas_msgpack,228003,1.672,0.00164,0.001346,0.019992,0.002762,0.021632,139.03,11.405,2893967,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polyhedrons,1000,compas_msgpack_zstd,129278,2.949,0.003835,0.00142,0.020469,0.000188,0.024304,33.71,6.316,3124947,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polyhedrons,10000,json,3812149,1.0,0.077866,0.013445,0.085492,0.003621,0.163358,48.958,44.591,18488497,True,True,True,0.0,0.0,"compact text, lossless" +polyhedrons,10000,json_zip,1460734,2.61,0.154422,0.015234,0.095562,0.003929,0.249983,9.459,15.286,18490994,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polyhedrons,10000,compas_pb,1850015,2.061,0.078424,0.000768,0.102964,0.010273,0.181387,23.59,17.968,13034707,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polyhedrons,10000,compas_pb_zip,934857,4.078,0.10015,0.000601,0.106632,0.001798,0.206782,9.335,8.767,14885702,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polyhedrons,10000,compas_pb_zstd,929108,4.103,0.090319,0.000529,0.106193,0.015315,0.196512,10.287,8.749,14884803,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polyhedrons,10000,compas_msgpack,2280003,1.672,0.016635,0.013632,0.255765,0.016449,0.2724,137.065,8.914,29147239,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polyhedrons,10000,compas_msgpack_zstd,1293815,2.946,0.033987,0.014298,0.26116,0.002259,0.295148,38.067,4.954,31429587,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polylines,1000,json,567347,1.0,0.013457,0.001626,0.014696,0.000127,0.028153,42.161,38.605,3091421,True,True,True,0.0,0.0,"compact text, lossless" +polylines,1000,json_zip,259472,2.187,0.028903,0.001627,0.015729,0.003053,0.044632,8.977,16.496,3094638,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polylines,1000,compas_pb,253015,2.242,0.00612,3.1e-05,0.014485,0.00017,0.020606,41.34,17.467,2422895,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polylines,1000,compas_pb_zip,185252,3.063,0.010648,0.000121,0.014799,0.00304,0.025447,17.397,12.518,2677942,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polylines,1000,compas_pb_zstd,183803,3.087,0.007663,9e-05,0.014336,0.000173,0.021999,23.986,12.821,2675943,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polylines,1000,compas_msgpack,313003,1.813,0.004451,0.001414,0.027732,0.003374,0.032183,70.316,11.287,3900909,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polylines,1000,compas_msgpack_zstd,234065,2.424,0.006551,0.001433,0.026829,0.003213,0.03338,35.731,8.724,4213481,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +polylines,10000,json,5673763,1.0,0.13687,0.014453,0.178463,0.011671,0.315333,41.454,31.792,30990429,True,True,True,0.0,0.0,"compact text, lossless" +polylines,10000,json_zip,2584656,2.195,0.298628,0.013701,0.186926,0.012855,0.485554,8.655,13.827,30992934,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +polylines,10000,compas_pb,2530017,2.243,0.062733,0.001349,0.171678,0.010011,0.23441,40.33,14.737,24315487,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +polylines,10000,compas_pb_zip,1850649,3.066,0.109933,0.000937,0.175413,0.010702,0.285346,16.834,10.55,26846728,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +polylines,10000,compas_pb_zstd,1833306,3.095,0.078656,0.000753,0.172057,0.011262,0.250713,23.308,10.655,26845713,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +polylines,10000,compas_msgpack,3130003,1.813,0.044646,0.014417,0.331796,0.01717,0.376442,70.107,9.434,39209013,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +polylines,10000,compas_msgpack_zstd,2289822,2.478,0.07059,0.015294,0.322143,0.027663,0.392733,32.438,7.108,42340521,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +projections,1000,json,192652,1.0,0.00381,0.00186,0.004366,7.9e-05,0.008176,50.558,44.13,1268288,True,True,True,0.0,0.0,"compact text, lossless" +projections,1000,json_zip,36502,5.278,0.005453,0.001347,0.004561,9.6e-05,0.010014,6.694,8.002,1270721,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +projections,1000,compas_pb,191015,1.009,0.005382,7.5e-05,0.006948,0.00274,0.01233,35.489,27.493,974009,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +projections,1000,compas_pb_zip,11957,16.112,0.006297,6.4e-05,0.006912,0.000131,0.013209,1.899,1.73,1166375,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +projections,1000,compas_pb_zstd,8993,21.422,0.006203,4.7e-05,0.006949,0.002453,0.013152,1.45,1.294,1165057,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +projections,1000,compas_msgpack,239003,0.806,0.00145,0.00144,0.013841,0.002909,0.015292,164.778,17.268,2133543,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +projections,1000,compas_msgpack_zstd,34530,5.579,0.002737,0.001483,0.013711,0.000253,0.016448,12.618,2.518,2375931,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +projections,10000,json,1926699,1.0,0.038528,0.013858,0.056102,0.006957,0.09463,50.007,34.343,12762991,True,True,True,0.0,0.0,"compact text, lossless" +projections,10000,json_zip,361121,5.335,0.052821,0.014216,0.059914,0.006841,0.112735,6.837,6.027,12765152,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +projections,10000,compas_pb,1910015,1.009,0.054147,0.000217,0.081103,0.006443,0.13525,35.275,23.55,9834497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +projections,10000,compas_pb_zip,117045,16.461,0.062188,0.000308,0.079289,0.004965,0.141477,1.882,1.476,11745740,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +projections,10000,compas_pb_zstd,88046,21.883,0.061943,0.00074,0.077279,0.005752,0.139222,1.421,1.139,11744545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +projections,10000,compas_msgpack,2390003,0.806,0.014666,0.013425,0.175206,0.013365,0.189872,162.961,13.641,21547223,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +projections,10000,compas_msgpack_zstd,333825,5.772,0.027175,0.013452,0.174464,0.013685,0.20164,12.284,1.913,23937259,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +quaternions,1000,json,189913,1.0,0.004311,0.001644,0.004464,0.000108,0.008774,44.058,42.547,581797,True,True,True,0.0,0.0,"compact text, lossless" +quaternions,1000,json_zip,66911,2.838,0.008111,0.004091,0.004492,8.9e-05,0.012603,8.249,14.895,584302,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +quaternions,1000,compas_pb,93015,2.042,0.00325,4.3e-05,0.004924,3.3e-05,0.008174,28.621,18.89,290333,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +quaternions,1000,compas_pb_zip,34587,5.491,0.004591,4.1e-05,0.005263,8.4e-05,0.009854,7.534,6.571,384576,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +quaternions,1000,compas_pb_zstd,33804,5.618,0.004015,5.8e-05,0.005004,2.3e-05,0.009018,8.42,6.756,383381,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +quaternions,1000,compas_msgpack,127003,1.495,0.001597,0.00138,0.005957,7.9e-05,0.007553,79.541,21.321,1009551,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +quaternions,1000,compas_msgpack_zstd,59725,3.18,0.003461,0.001363,0.006127,9.6e-05,0.009588,17.257,9.748,1136587,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +quaternions,10000,json,1899463,1.0,0.038656,0.014339,0.041025,0.004429,0.079681,49.138,46.3,5859715,True,True,True,0.0,0.0,"compact text, lossless" +quaternions,10000,json_zip,661864,2.87,0.072818,0.013796,0.045163,0.00432,0.117982,9.089,14.655,5862172,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +quaternions,10000,compas_pb,930015,2.042,0.033135,0.000194,0.051301,0.002891,0.084437,28.067,18.129,2958653,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +quaternions,10000,compas_pb_zip,343792,5.525,0.044299,0.001081,0.05105,0.000393,0.095349,7.761,6.734,3890432,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +quaternions,10000,compas_pb_zstd,335374,5.664,0.038085,0.000556,0.050605,0.003332,0.08869,8.806,6.627,3888701,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +quaternions,10000,compas_msgpack,1270003,1.496,0.015906,0.013863,0.069792,0.004602,0.085699,79.843,18.197,10270191,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +quaternions,10000,compas_msgpack_zstd,588176,3.229,0.029667,0.014029,0.071006,0.004553,0.100673,19.826,8.283,11540227,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +reflections,1000,json,193892,1.0,0.0039,0.001564,0.004381,7.6e-05,0.008281,49.713,44.255,1269464,True,True,True,0.0,0.0,"compact text, lossless" +reflections,1000,json_zip,36509,5.311,0.005417,0.001613,0.004665,0.000129,0.010082,6.74,7.827,1271969,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +reflections,1000,compas_pb,191015,1.015,0.005581,9.5e-05,0.006905,0.000154,0.012486,34.226,27.663,974009,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +reflections,1000,compas_pb_zip,11925,16.259,0.006462,9.8e-05,0.007075,4.5e-05,0.013537,1.845,1.686,1166252,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +reflections,1000,compas_pb_zstd,8976,21.601,0.006264,0.000177,0.007143,0.000107,0.013407,1.433,1.257,1165057,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +reflections,1000,compas_msgpack,239003,0.811,0.001524,0.001438,0.013809,4.4e-05,0.015333,156.873,17.308,2133543,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +reflections,1000,compas_msgpack_zstd,34473,5.624,0.002688,0.0014,0.013529,5.3e-05,0.016217,12.825,2.548,2372579,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +reflections,10000,json,1939351,1.0,0.039505,0.015484,0.058999,0.002655,0.098503,49.092,32.871,12775643,True,True,True,0.0,0.0,"compact text, lossless" +reflections,10000,json_zip,361749,5.361,0.054109,0.013906,0.061723,0.003682,0.115831,6.686,5.861,12778500,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +reflections,10000,compas_pb,1910015,1.015,0.054198,0.000526,0.080347,0.006008,0.134545,35.242,23.772,9834497,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +reflections,10000,compas_pb_zip,116593,16.634,0.064351,0.001099,0.08062,0.006881,0.144971,1.812,1.446,11745740,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +reflections,10000,compas_pb_zstd,87875,22.069,0.066365,0.00459,0.084884,0.006926,0.151248,1.324,1.035,11744545,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +reflections,10000,compas_msgpack,2390003,0.811,0.015129,0.013266,0.16213,0.012225,0.177259,157.976,14.741,21549535,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +reflections,10000,compas_msgpack_zstd,332767,5.828,0.031147,0.012848,0.177685,0.013694,0.208832,10.684,1.873,23937259,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +rotations,1000,json,238876,1.0,0.004828,0.001477,0.004562,3.4e-05,0.00939,49.477,52.361,1314446,True,True,True,0.0,0.0,"compact text, lossless" +rotations,1000,json_zip,53049,4.503,0.007567,0.001565,0.004821,0.002951,0.012388,7.01,11.004,1316943,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +rotations,1000,compas_pb,77015,3.102,0.008747,7.9e-05,0.015941,5.3e-05,0.024688,8.805,4.831,880311,False,False,False,1.457167719820518e-15,6.79933712578244e-17,"protobuf binary, double + flat arrays (optimized)" +rotations,1000,compas_pb_zip,8967,26.639,0.009119,2.1e-05,0.016318,0.002445,0.025437,0.983,0.55,958554,False,False,False,1.457167719820518e-15,6.79933712578244e-17,"protobuf binary, zip-compressed" +rotations,1000,compas_pb_zstd,8232,29.018,0.009443,0.000136,0.016283,9.1e-05,0.025726,0.872,0.506,957359,False,False,False,1.457167719820518e-15,6.79933712578244e-17,"protobuf binary, zstandard-compressed" +rotations,1000,compas_msgpack,237003,1.008,0.001523,0.001317,0.01386,0.000143,0.015383,155.62,17.099,2131541,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +rotations,1000,compas_msgpack_zstd,51541,4.635,0.00313,0.001371,0.013982,0.002503,0.017113,16.465,3.686,2368577,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +rotations,10000,json,2388712,1.0,0.048099,0.013711,0.064779,0.004101,0.112878,49.662,36.875,13225002,True,True,True,0.0,0.0,"compact text, lossless" +rotations,10000,json_zip,527145,4.531,0.077994,0.01427,0.062349,0.008611,0.140344,6.759,8.455,13227171,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +rotations,10000,compas_pb,770015,3.102,0.088225,0.000572,0.174113,0.007927,0.262338,8.728,4.422,8877103,False,False,False,1.582067810090848e-15,6.517959784606405e-17,"protobuf binary, double + flat arrays (optimized)" +rotations,10000,compas_pb_zip,87393,27.333,0.090942,9.8e-05,0.170866,0.006672,0.261808,0.961,0.511,9648346,False,False,False,1.582067810090848e-15,6.517959784606405e-17,"protobuf binary, zip-compressed" +rotations,10000,compas_pb_zstd,81273,29.391,0.090704,0.000313,0.169394,0.005858,0.260098,0.896,0.48,9647151,False,False,False,1.582067810090848e-15,6.517959784606405e-17,"protobuf binary, zstandard-compressed" +rotations,10000,compas_msgpack,2370003,1.008,0.014749,0.013445,0.171579,0.010098,0.186328,160.69,13.813,21527221,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +rotations,10000,compas_msgpack_zstd,500974,4.768,0.028934,0.014164,0.170957,0.011779,0.199891,17.314,2.93,23897257,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +scales,1000,json,216077,1.0,0.004376,0.001634,0.004588,0.000233,0.008964,49.377,47.094,1291644,True,True,True,0.0,0.0,"compact text, lossless" +scales,1000,json_zip,58022,3.724,0.006744,0.001477,0.004759,0.002847,0.011503,8.604,12.193,1294901,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +scales,1000,compas_pb,186015,1.162,0.005348,7.4e-05,0.00692,9.4e-05,0.012269,34.78,26.879,974004,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +scales,1000,compas_pb_zip,26602,8.123,0.006368,0.000109,0.007067,0.002752,0.013435,4.178,3.764,1161247,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +scales,1000,compas_pb_zstd,24855,8.694,0.007178,0.000459,0.007492,0.000223,0.01467,3.463,3.318,1160052,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +scales,1000,compas_msgpack,234003,0.923,0.001466,0.001447,0.013857,0.00246,0.015323,159.602,16.887,2128538,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +scales,1000,compas_msgpack_zstd,52789,4.093,0.003251,0.00147,0.014114,0.002329,0.017365,16.236,3.74,2362574,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +scales,10000,json,2160302,1.0,0.043204,0.013676,0.059377,0.002864,0.102581,50.003,36.383,12996253,True,True,True,0.0,0.0,"compact text, lossless" +scales,10000,json_zip,574700,3.759,0.070976,0.013757,0.058749,0.005669,0.129725,8.097,9.782,12999086,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +scales,10000,compas_pb,1860015,1.161,0.054923,0.000157,0.085468,0.007624,0.140391,33.866,21.763,9834492,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +scales,10000,compas_pb_zip,263513,8.198,0.062261,0.000964,0.080139,0.005376,0.142401,4.232,3.288,11695735,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +scales,10000,compas_pb_zstd,247439,8.731,0.067288,0.001439,0.080594,0.00485,0.147882,3.677,3.07,11694540,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +scales,10000,compas_msgpack,2340003,0.923,0.01472,0.013583,0.177101,0.012736,0.191821,158.964,13.213,21499530,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +scales,10000,compas_msgpack_zstd,515417,4.191,0.031908,0.013761,0.16894,0.009994,0.200848,16.153,3.051,23837254,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +shears,1000,json,190198,1.0,0.003898,0.001627,0.004244,0.000155,0.008142,48.79,44.821,1265765,True,True,True,0.0,0.0,"compact text, lossless" +shears,1000,json_zip,35238,5.398,0.006331,0.001687,0.00461,0.002868,0.010941,5.566,7.644,1269030,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +shears,1000,compas_pb,186015,1.022,0.005385,6.2e-05,0.006881,0.000123,0.012266,34.545,27.034,974004,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +shears,1000,compas_pb_zip,9282,20.491,0.005929,3.6e-05,0.006964,0.002861,0.012893,1.566,1.333,1161247,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +shears,1000,compas_pb_zstd,8084,23.528,0.006166,5.4e-05,0.006846,0.000132,0.013012,1.311,1.181,1160052,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +shears,1000,compas_msgpack,234003,0.813,0.001495,0.00144,0.013747,0.002268,0.015242,156.524,17.022,2128538,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +shears,1000,compas_msgpack_zstd,34284,5.548,0.002637,0.001457,0.013597,0.002264,0.016234,13.001,2.521,2362574,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +shears,10000,json,1902085,1.0,0.038593,0.013952,0.057974,0.002792,0.096567,49.286,32.809,12738372,True,True,True,0.0,0.0,"compact text, lossless" +shears,10000,json_zip,348628,5.456,0.05396,0.014077,0.056015,0.006749,0.109975,6.461,6.224,12740877,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +shears,10000,compas_pb,1860015,1.023,0.053393,0.000178,0.080391,0.006949,0.133784,34.837,23.137,9834492,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +shears,10000,compas_pb_zip,90503,21.017,0.058949,0.000784,0.080749,0.007478,0.139698,1.535,1.121,11695731,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +shears,10000,compas_pb_zstd,79349,23.971,0.062757,0.001003,0.079357,0.006845,0.142114,1.264,1.0,11694540,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +shears,10000,compas_msgpack,2340003,0.813,0.014455,0.013653,0.177389,0.016763,0.191843,161.884,13.191,21497218,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +shears,10000,compas_msgpack_zstd,332048,5.728,0.025292,0.013989,0.174854,0.014722,0.200147,13.128,1.899,23837254,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +spheres,1000,json,237252,1.0,0.006343,0.001627,0.03726,0.002717,0.043603,37.405,6.367,1630917,True,True,True,0.0,0.0,"compact text, lossless" +spheres,1000,json_zip,68294,3.474,0.009821,0.001775,0.039578,0.00358,0.049399,6.954,1.726,1633422,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +spheres,1000,compas_pb,115015,2.063,0.006386,2.6e-05,0.0444,0.001184,0.050786,18.01,2.59,1291821,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +spheres,1000,compas_pb_zip,35118,6.756,0.007397,6.8e-05,0.044486,0.000805,0.051882,4.748,0.789,1408060,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +spheres,1000,compas_pb_zstd,33203,7.145,0.007326,8.2e-05,0.044392,0.000438,0.051718,4.532,0.748,1406869,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +spheres,1000,compas_msgpack,204003,1.163,0.003381,0.001479,0.046164,0.002712,0.049546,60.334,4.419,2619787,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +spheres,1000,compas_msgpack_zstd,62189,3.815,0.004961,0.00146,0.045072,0.004106,0.050033,12.535,1.38,2823359,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +spheres,10000,json,2372345,1.0,0.070988,0.016914,0.40167,0.003757,0.472658,33.419,5.906,16334546,True,True,True,0.0,0.0,"compact text, lossless" +spheres,10000,json_zip,677484,3.502,0.096548,0.017133,0.40235,0.003772,0.498898,7.017,1.684,16337051,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +spheres,10000,compas_pb,1150015,2.063,0.063988,0.000434,0.460744,0.017278,0.524733,17.972,2.496,12960429,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +spheres,10000,compas_pb_zip,348595,6.805,0.075939,0.000303,0.463663,0.004162,0.539602,4.59,0.752,14111616,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +spheres,10000,compas_pb_zstd,334774,7.086,0.075876,0.001202,0.448751,0.001243,0.524628,4.412,0.746,14110477,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +spheres,10000,compas_msgpack,2040003,1.163,0.032622,0.015426,0.472016,0.010915,0.504638,62.534,4.322,26391899,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +spheres,10000,compas_msgpack_zstd,609033,3.895,0.045836,0.015338,0.469159,0.010308,0.514995,13.287,1.298,28431935,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +toruses,1000,json,273906,1.0,0.006866,0.001652,0.037552,0.002744,0.044418,39.896,7.294,1691642,True,True,True,0.0,0.0,"compact text, lossless" +toruses,1000,json_zip,78999,3.467,0.010535,0.001697,0.039193,0.002721,0.049728,7.499,2.016,1694907,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +toruses,1000,compas_pb,123015,2.227,0.00697,0.000185,0.043589,0.000729,0.050559,17.649,2.822,1315828,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +toruses,1000,compas_pb_zip,43350,6.318,0.007585,0.000127,0.043713,5.6e-05,0.051298,5.715,0.992,1440071,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +toruses,1000,compas_pb_zstd,41395,6.617,0.007201,3.1e-05,0.043472,0.003209,0.050673,5.748,0.952,1438876,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +toruses,1000,compas_msgpack,229003,1.196,0.003239,0.001537,0.044632,0.003074,0.04787,70.708,5.131,2756794,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +toruses,1000,compas_msgpack_zstd,70653,3.877,0.005084,0.001479,0.044712,0.002733,0.049795,13.897,1.58,2985366,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +toruses,10000,json,2738988,1.0,0.072871,0.021004,0.400758,0.001607,0.47363,37.587,6.835,16941260,True,True,True,0.0,0.0,"compact text, lossless" +toruses,10000,json_zip,783813,3.494,0.102428,0.016229,0.40531,0.001129,0.507739,7.652,1.934,16943765,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +toruses,10000,compas_pb,1230015,2.227,0.06549,7.3e-05,0.448161,0.012444,0.513651,18.782,2.745,13200308,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +toruses,10000,compas_pb_zip,430957,6.356,0.079417,0.002805,0.457097,0.0009,0.536513,5.427,0.943,14431615,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +toruses,10000,compas_pb_zstd,410383,6.674,0.073244,0.000624,0.459236,0.001931,0.53248,5.603,0.894,14430420,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +toruses,10000,compas_msgpack,2290003,1.196,0.03316,0.01524,0.477497,0.009803,0.510657,69.06,4.796,27761522,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +toruses,10000,compas_msgpack_zstd,692920,3.953,0.052542,0.015282,0.490513,0.008679,0.543055,13.188,1.413,30050454,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +transformations,1000,json,225071,1.0,0.004424,0.001501,0.004524,0.000156,0.008948,50.876,49.754,1300647,True,True,True,0.0,0.0,"compact text, lossless" +transformations,1000,json_zip,59728,3.768,0.006784,0.001515,0.004768,0.003009,0.011552,8.804,12.527,1303912,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +transformations,1000,compas_pb,195015,1.154,0.005622,8e-06,0.00671,0.000181,0.012332,34.687,29.064,973949,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +transformations,1000,compas_pb_zip,28931,7.78,0.006593,6.6e-05,0.007077,0.002564,0.013669,4.388,4.088,1170192,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +transformations,1000,compas_pb_zstd,24131,9.327,0.006786,8.3e-05,0.006668,7.6e-05,0.013454,3.556,3.619,1168997,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +transformations,1000,compas_msgpack,243003,0.926,0.001496,0.003894,0.013392,0.000219,0.014888,162.453,18.145,2137547,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +transformations,1000,compas_msgpack_zstd,52848,4.259,0.003293,0.00138,0.013608,0.002599,0.016901,16.05,3.884,2380583,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +transformations,10000,json,2250530,1.0,0.044675,0.014994,0.060764,0.00442,0.10544,50.375,37.037,13086826,True,True,True,0.0,0.0,"compact text, lossless" +transformations,10000,json_zip,592472,3.799,0.070611,0.014013,0.059306,0.006434,0.129917,8.391,9.99,13089323,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +transformations,10000,compas_pb,1950015,1.154,0.05464,0.00034,0.079484,0.00784,0.134125,35.688,24.533,9834437,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +transformations,10000,compas_pb_zip,285055,7.895,0.067264,0.000329,0.079068,0.005121,0.146332,4.238,3.605,11785676,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +transformations,10000,compas_pb_zstd,248334,9.063,0.067458,0.000859,0.07716,0.006791,0.144618,3.681,3.218,11784485,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +transformations,10000,compas_msgpack,2430003,0.926,0.014819,0.013423,0.172686,0.01388,0.187506,163.975,14.072,21587227,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +transformations,10000,compas_msgpack_zstd,515047,4.37,0.033154,0.013538,0.178584,0.01411,0.211738,15.535,2.884,24017263,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +translations,1000,json,222071,1.0,0.004585,0.001511,0.004659,5.5e-05,0.009245,48.43,47.661,1297644,True,True,True,0.0,0.0,"compact text, lossless" +translations,1000,json_zip,59704,3.72,0.007076,0.002008,0.005196,0.003554,0.012272,8.437,11.491,1300149,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +translations,1000,compas_pb,87015,2.552,0.005496,0.000102,0.008973,0.000214,0.014469,15.833,9.697,662234,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +translations,1000,compas_pb_zip,26120,8.502,0.00635,2.3e-05,0.009189,0.002924,0.015539,4.113,2.842,750477,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +translations,1000,compas_pb_zstd,24965,8.895,0.006021,8.3e-05,0.008968,5.5e-05,0.01499,4.146,2.784,749282,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +translations,1000,compas_msgpack,240003,0.925,0.001526,0.001667,0.014013,2e-05,0.01554,157.263,17.127,2134544,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +translations,1000,compas_msgpack_zstd,52789,4.207,0.003573,0.001368,0.014334,0.003283,0.017907,14.774,3.683,2374580,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +translations,10000,json,2220530,1.0,0.04738,0.013745,0.066811,0.004845,0.114191,46.866,33.236,13056487,True,True,True,0.0,0.0,"compact text, lossless" +translations,10000,json_zip,591919,3.751,0.071127,0.014464,0.062838,0.007139,0.133966,8.322,9.42,13059328,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +translations,10000,compas_pb,870015,2.552,0.054543,0.000245,0.102329,0.008314,0.156872,15.951,8.502,6714962,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +translations,10000,compas_pb_zip,258794,8.58,0.059831,0.000565,0.097725,0.006052,0.157557,4.325,2.648,7586205,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +translations,10000,compas_pb_zstd,247452,8.974,0.058362,0.00165,0.097394,0.005722,0.155756,4.24,2.541,7585010,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +translations,10000,compas_msgpack,2400003,0.925,0.014601,0.013508,0.168838,0.012388,0.18344,164.37,14.215,21557224,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +translations,10000,compas_msgpack_zstd,514901,4.313,0.031762,0.017672,0.172148,0.012435,0.20391,16.211,2.991,23957260,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +vectors,1000,json,146071,1.0,0.003462,0.001467,0.003638,0.000115,0.0071,42.19,40.152,513823,True,True,True,0.0,0.0,"compact text, lossless" +vectors,1000,json_zip,56052,2.606,0.006786,0.001337,0.004203,0.000306,0.010989,8.26,13.336,516320,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +vectors,1000,compas_pb,80015,1.826,0.003264,3.4e-05,0.004939,1.6e-05,0.008203,24.514,16.202,266345,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +vectors,1000,compas_pb_zip,26096,5.597,0.003875,5.6e-05,0.00503,6e-06,0.008904,6.735,5.188,347588,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +vectors,1000,compas_pb_zstd,24962,5.852,0.00368,1.5e-05,0.004938,3.3e-05,0.008618,6.783,5.055,346393,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +vectors,1000,compas_msgpack,106003,1.378,0.001688,0.001414,0.005226,0.000132,0.006914,62.793,20.283,825072,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +vectors,1000,compas_msgpack_zstd,51828,2.818,0.002764,0.00139,0.005746,0.000218,0.00851,18.751,9.02,931108,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" +vectors,10000,json,1460530,1.0,0.034591,0.015218,0.038533,0.004668,0.073124,42.223,37.903,5180650,True,True,True,0.0,0.0,"compact text, lossless" +vectors,10000,json_zip,552931,2.641,0.06012,0.014823,0.04141,0.004643,0.10153,9.197,13.353,5183107,True,True,True,0.0,0.0,"zip-compressed json, size baseline" +vectors,10000,compas_pb,800015,1.826,0.033087,8.7e-05,0.050891,0.003232,0.083978,24.179,15.72,2718665,True,True,True,0.0,0.0,"protobuf binary, double + flat arrays (optimized)" +vectors,10000,compas_pb_zip,258630,5.647,0.039964,0.000396,0.051548,0.000463,0.091512,6.472,5.017,3519979,True,True,True,0.0,0.0,"protobuf binary, zip-compressed" +vectors,10000,compas_pb_zstd,249995,5.842,0.036337,3.8e-05,0.050338,0.002912,0.086675,6.88,4.966,3518713,True,True,True,0.0,0.0,"protobuf binary, zstandard-compressed" +vectors,10000,compas_msgpack,1060003,1.378,0.016567,0.013833,0.053364,0.004319,0.069931,63.984,19.863,8467704,True,True,True,0.0,0.0,msgpack over the JSON-shape tree (Kumiki-style) +vectors,10000,compas_msgpack_zstd,506934,2.881,0.028585,0.014407,0.055849,0.004563,0.084433,17.734,9.077,9527740,True,True,True,0.0,0.0,"msgpack, zstandard-compressed" diff --git a/benchmarks/serialization/results/baseline_quick.html b/benchmarks/serialization/results/baseline_quick.html index e8479a5a4f0b..6edfa11fffbc 100644 --- a/benchmarks/serialization/results/baseline_quick.html +++ b/benchmarks/serialization/results/baseline_quick.html @@ -87,7 +87,11 @@ .segmented button.active { background: var(--surface); color: var(--text-primary); font-weight: 600; box-shadow: 0 1px 2px rgba(0,0,0,0.10); } .tile .rng { font-size: 11px; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; } -

COMPAS serialization benchmark

generated 2026-07-10 18:06 · preset quick · repeat 3 · seed 42 · compas 2.15.0-c8a587f3

Show formats
json · compact text, losslessjson_zip · zip-compressed json, size baselinecompas_pb · protobuf binary, double + flat arrays (optimized)compas_pb_zip · protobuf binary, zip-compressedcompas_pb_zstd · protobuf binary, zstandard-compressedcompas_msgpack · msgpack over the JSON-shape tree (Kumiki-style)compas_msgpack_zstd · msgpack, zstandard-compressed

beziers

Round-trip time
1,000 elements
json
17.8 ms
json_zip
26.3 ms
compas_pb
15.3 ms
compas_pb_zip
17.8 ms
compas_pb_zstd
16.8 ms
compas_msgpack
19.4 ms
compas_msgpack_zstd
22.3 ms
10,000 elements
json
200.3 ms
json_zip
288.6 ms
compas_pb
170.2 ms
compas_pb_zip
200.1 ms
compas_pb_zstd
187.8 ms
compas_msgpack
240.7 ms
compas_msgpack_zstd
249.4 ms
Wire size
1,000 elements
json
325.4 KB
json_zip
141.8 KB
compas_pb
151.4 KB
compas_pb_zip
91.3 KB
compas_pb_zstd
90.1 KB
compas_msgpack
194.3 KB
compas_msgpack_zstd
125.8 KB
10,000 elements
json
3.2 MB
json_zip
1.4 MB
compas_pb
1.5 MB
compas_pb_zip
911.6 KB
compas_pb_zstd
904.5 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
1.2 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json325.4 KB1.0×8.1 ms9.8 ms17.8 ms34.0431.7 MB0✓ yes
1,000json_zip141.8 KB2.294×16.2 ms10.0 ms26.3 ms14.4881.7 MB0✓ yes
1,000compas_pb151.4 KB2.15×4.9 ms10.4 ms15.3 ms14.9581.3 MB0✓ yes
1,000compas_pb_zip91.3 KB3.563×6.9 ms10.8 ms17.8 ms8.6221.4 MB0✓ yes
1,000compas_pb_zstd90.1 KB3.61×5.8 ms11.0 ms16.8 ms8.411.4 MB0✓ yes
1,000compas_msgpack194.3 KB1.674×3.0 ms16.5 ms19.4 ms12.0742.3 MB0✓ yes
1,000compas_msgpack_zstd125.8 KB2.587×5.4 ms16.9 ms22.3 ms7.6192.5 MB0✓ yes
10,000json3.2 MB1.0×84.6 ms115.8 ms200.3 ms28.78516.9 MB0✓ yes
10,000json_zip1.4 MB2.309×162.2 ms126.4 ms288.6 ms11.41416.9 MB0✓ yes
10,000compas_pb1.5 MB2.15×47.4 ms122.9 ms170.2 ms12.61512.8 MB0✓ yes
10,000compas_pb_zip911.6 KB3.57×73.7 ms126.4 ms200.1 ms7.38314.3 MB0✓ yes
10,000compas_pb_zstd904.5 KB3.597×63.2 ms124.6 ms187.8 ms7.43514.3 MB0✓ yes
10,000compas_msgpack1.9 MB1.674×30.4 ms210.2 ms240.7 ms9.46723.6 MB0✓ yes
10,000compas_msgpack_zstd1.2 MB2.581×48.9 ms200.5 ms249.4 ms6.4425.5 MB0✓ yes

boxes

Round-trip time
1,000 elements
json
45.9 ms
json_zip
50.2 ms
compas_pb
50.5 ms
compas_pb_zip
53.3 ms
compas_pb_zstd
53.1 ms
compas_msgpack
49.0 ms
compas_msgpack_zstd
51.0 ms
10,000 elements
json
488.1 ms
json_zip
568.4 ms
compas_pb
543.3 ms
compas_pb_zip
560.2 ms
compas_pb_zstd
551.7 ms
compas_msgpack
540.9 ms
compas_msgpack_zstd
558.7 ms
Wire size
1,000 elements
json
278.9 KB
json_zip
87.7 KB
compas_pb
127.9 KB
compas_pb_zip
51.1 KB
compas_pb_zstd
48.9 KB
compas_msgpack
224.6 KB
compas_msgpack_zstd
77.6 KB
10,000 elements
json
2.7 MB
json_zip
871.1 KB
compas_pb
1.2 MB
compas_pb_zip
508.7 KB
compas_pb_zstd
485.5 KB
compas_msgpack
2.2 MB
compas_msgpack_zstd
776.8 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json278.9 KB1.0×7.3 ms38.5 ms45.9 ms7.4091.6 MB0✓ yes
1,000json_zip87.7 KB3.178×11.3 ms39.0 ms50.2 ms2.3061.6 MB0✓ yes
1,000compas_pb127.9 KB2.18×6.4 ms44.1 ms50.5 ms2.9741.3 MB0✓ yes
1,000compas_pb_zip51.1 KB5.46×8.8 ms44.5 ms53.3 ms1.1741.4 MB0✓ yes
1,000compas_pb_zstd48.9 KB5.706×7.8 ms45.3 ms53.1 ms1.1061.4 MB0✓ yes
1,000compas_msgpack224.6 KB1.242×3.3 ms45.7 ms49.0 ms5.0322.5 MB0✓ yes
1,000compas_msgpack_zstd77.6 KB3.594×5.4 ms45.6 ms51.0 ms1.7432.8 MB0✓ yes
10,000json2.7 MB1.0×74.4 ms413.7 ms488.1 ms6.90316.5 MB0✓ yes
10,000json_zip871.1 KB3.201×119.0 ms449.4 ms568.4 ms1.98516.5 MB0✓ yes
10,000compas_pb1.2 MB2.18×67.1 ms476.2 ms543.3 ms2.75112.8 MB0✓ yes
10,000compas_pb_zip508.7 KB5.482×80.9 ms479.4 ms560.2 ms1.08714.1 MB0✓ yes
10,000compas_pb_zstd485.5 KB5.743×80.4 ms471.3 ms551.7 ms1.05514.1 MB0✓ yes
10,000compas_msgpack2.2 MB1.241×34.2 ms506.8 ms540.9 ms4.53825.6 MB0✓ yes
10,000compas_msgpack_zstd776.8 KB3.589×61.8 ms497.0 ms558.7 ms1.60127.8 MB0✓ yes

circles

Round-trip time
1,000 elements
json
45.3 ms
json_zip
48.0 ms
compas_pb
53.0 ms
compas_pb_zip
55.4 ms
compas_pb_zstd
54.7 ms
compas_msgpack
47.6 ms
compas_msgpack_zstd
49.2 ms
10,000 elements
json
475.6 ms
json_zip
510.5 ms
compas_pb
559.2 ms
compas_pb_zip
595.7 ms
compas_pb_zstd
578.5 ms
compas_msgpack
526.7 ms
compas_msgpack_zstd
533.2 ms
Wire size
1,000 elements
json
231.6 KB
json_zip
66.7 KB
compas_pb
159.2 KB
compas_pb_zip
62.0 KB
compas_pb_zstd
60.6 KB
compas_msgpack
199.2 KB
compas_msgpack_zstd
60.7 KB
10,000 elements
json
2.3 MB
json_zip
661.6 KB
compas_pb
1.6 MB
compas_pb_zip
616.9 KB
compas_pb_zstd
592.3 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
594.7 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json231.6 KB1.0×6.6 ms38.7 ms45.3 ms6.1371.5 MB0✓ yes
1,000json_zip66.7 KB3.475×9.2 ms38.8 ms48.0 ms1.7581.5 MB0✓ yes
1,000compas_pb159.2 KB1.455×7.6 ms45.4 ms53.0 ms3.5921.3 MB0✓ yes
1,000compas_pb_zip62.0 KB3.735×9.6 ms45.9 ms55.4 ms1.3851.5 MB0✓ yes
1,000compas_pb_zstd60.6 KB3.825×9.0 ms45.6 ms54.7 ms1.3591.5 MB0✓ yes
1,000compas_msgpack199.2 KB1.163×3.2 ms44.4 ms47.6 ms4.5912.4 MB0✓ yes
1,000compas_msgpack_zstd60.7 KB3.815×4.7 ms44.5 ms49.2 ms1.3982.6 MB0✓ yes
10,000json2.3 MB1.0×66.7 ms408.9 ms475.6 ms5.80114.7 MB0✓ yes
10,000json_zip661.6 KB3.502×98.1 ms412.4 ms510.5 ms1.64314.7 MB0✓ yes
10,000compas_pb1.6 MB1.455×76.8 ms482.4 ms559.2 ms3.37913.0 MB0✓ yes
10,000compas_pb_zip616.9 KB3.755×102.0 ms493.7 ms595.7 ms1.2814.6 MB0✓ yes
10,000compas_pb_zstd592.3 KB3.911×90.0 ms488.5 ms578.5 ms1.24214.6 MB0✓ yes
10,000compas_msgpack1.9 MB1.163×34.0 ms492.8 ms526.7 ms4.1424.3 MB0✓ yes
10,000compas_msgpack_zstd594.7 KB3.895×46.1 ms487.1 ms533.2 ms1.2526.3 MB0✓ yes

frames

Round-trip time
1,000 elements
json
26.7 ms
json_zip
35.0 ms
compas_pb
30.7 ms
compas_pb_zip
33.3 ms
compas_pb_zstd
32.8 ms
compas_msgpack
27.7 ms
compas_msgpack_zstd
29.8 ms
10,000 elements
json
295.0 ms
json_zip
356.7 ms
compas_pb
325.4 ms
compas_pb_zip
358.3 ms
compas_pb_zstd
337.2 ms
compas_msgpack
321.7 ms
compas_msgpack_zstd
341.0 ms
Wire size
1,000 elements
json
288.9 KB
json_zip
107.2 KB
compas_pb
137.7 KB
compas_pb_zip
69.8 KB
compas_pb_zstd
68.1 KB
compas_msgpack
175.8 KB
compas_msgpack_zstd
94.4 KB
10,000 elements
json
2.8 MB
json_zip
1.0 MB
compas_pb
1.3 MB
compas_pb_zip
695.9 KB
compas_pb_zstd
690.5 KB
compas_msgpack
1.7 MB
compas_msgpack_zstd
941.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json288.9 KB1.0×7.1 ms19.7 ms26.7 ms15.0371.3 MB4.4e-16✗ no
1,000json_zip107.2 KB2.695×13.7 ms21.3 ms35.0 ms5.1441.3 MB4.4e-16✗ no
1,000compas_pb137.7 KB2.098×5.5 ms25.2 ms30.7 ms5.604964.4 KB4.4e-16✗ no
1,000compas_pb_zip69.8 KB4.14×7.9 ms25.4 ms33.3 ms2.8161.1 MB4.4e-16✗ no
1,000compas_pb_zstd68.1 KB4.241×6.7 ms26.1 ms32.8 ms2.6711.1 MB4.4e-16✗ no
1,000compas_msgpack175.8 KB1.644×2.9 ms24.8 ms27.7 ms7.2682.0 MB4.4e-16✗ no
1,000compas_msgpack_zstd94.4 KB3.062×4.8 ms25.0 ms29.8 ms3.8622.2 MB4.4e-16✗ no
10,000json2.8 MB1.0×79.4 ms215.6 ms295.0 ms13.72513.2 MB5.6e-16✗ no
10,000json_zip1.0 MB2.714×138.2 ms218.4 ms356.7 ms4.99113.2 MB5.6e-16✗ no
10,000compas_pb1.3 MB2.099×59.9 ms265.6 ms325.4 ms5.319.5 MB5.6e-16✗ no
10,000compas_pb_zip695.9 KB4.153×85.9 ms272.4 ms358.3 ms2.61610.8 MB5.6e-16✗ no
10,000compas_pb_zstd690.5 KB4.186×67.4 ms269.8 ms337.2 ms2.6210.8 MB5.6e-16✗ no
10,000compas_msgpack1.7 MB1.644×31.5 ms290.2 ms321.7 ms6.20220.0 MB5.6e-16✗ no
10,000compas_msgpack_zstd941.5 KB3.07×53.1 ms287.9 ms341.0 ms3.34821.8 MB5.6e-16✗ no

graph

Round-trip time
1,000 elements
json
14.2 ms
json_zip
16.0 ms
compas_pb
8.3 ms
compas_pb_zip
8.7 ms
compas_pb_zstd
8.0 ms
compas_msgpack
14.9 ms
compas_msgpack_zstd
15.8 ms
10,000 elements
json
150.6 ms
json_zip
160.1 ms
compas_pb
78.1 ms
compas_pb_zip
85.3 ms
compas_pb_zstd
78.4 ms
compas_msgpack
177.3 ms
compas_msgpack_zstd
191.2 ms
Wire size
1,000 elements
json
74.9 KB
json_zip
23.8 KB
compas_pb
36.3 KB
compas_pb_zip
15.1 KB
compas_pb_zstd
15.7 KB
compas_msgpack
52.6 KB
compas_msgpack_zstd
17.3 KB
10,000 elements
json
775.1 KB
json_zip
208.4 KB
compas_pb
360.2 KB
compas_pb_zip
139.4 KB
compas_pb_zstd
181.5 KB
compas_msgpack
551.6 KB
compas_msgpack_zstd
116.2 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json74.9 KB1.0×1.8 ms12.4 ms14.2 ms6.2041.8 MB0✓ yes
1,000json_zip23.8 KB3.153×3.6 ms12.4 ms16.0 ms1.9671.9 MB0✓ yes
1,000compas_pb36.3 KB2.064×4.3 ms4.0 ms8.3 ms9.3051.1 MB0✓ yes
1,000compas_pb_zip15.1 KB4.961×4.8 ms3.9 ms8.7 ms4.0151.1 MB0✓ yes
1,000compas_pb_zstd15.7 KB4.774×4.3 ms3.8 ms8.0 ms4.2831.1 MB0✓ yes
1,000compas_msgpack52.6 KB1.424×0.6 ms14.3 ms14.9 ms3.7732.4 MB0✓ yes
1,000compas_msgpack_zstd17.3 KB4.324×1.2 ms14.6 ms15.8 ms1.2142.5 MB0✓ yes
10,000json775.1 KB1.0×16.5 ms134.2 ms150.6 ms5.91618.2 MB0✓ yes
10,000json_zip208.4 KB3.719×34.4 ms125.7 ms160.1 ms1.69818.1 MB0✓ yes
10,000compas_pb360.2 KB2.152×40.6 ms37.5 ms78.1 ms9.83810.5 MB0✓ yes
10,000compas_pb_zip139.4 KB5.561×47.1 ms38.2 ms85.3 ms3.73610.9 MB0✓ yes
10,000compas_pb_zstd181.5 KB4.271×41.3 ms37.1 ms78.4 ms5.00410.9 MB0✓ yes
10,000compas_msgpack551.6 KB1.405×6.6 ms170.6 ms177.3 ms3.31124.0 MB0✓ yes
10,000compas_msgpack_zstd116.2 KB6.672×11.7 ms179.5 ms191.2 ms0.66324.5 MB0✓ yes

lines

Round-trip time
1,000 elements
json
15.9 ms
json_zip
21.1 ms
compas_pb
18.4 ms
compas_pb_zip
21.1 ms
compas_pb_zstd
19.4 ms
compas_msgpack
16.4 ms
compas_msgpack_zstd
18.3 ms
10,000 elements
json
170.7 ms
json_zip
221.3 ms
compas_pb
199.6 ms
compas_pb_zip
211.0 ms
compas_pb_zstd
206.7 ms
compas_msgpack
183.1 ms
compas_msgpack_zstd
198.7 ms
Wire size
1,000 elements
json
213.0 KB
json_zip
85.0 KB
compas_pb
106.5 KB
compas_pb_zip
50.6 KB
compas_pb_zstd
49.0 KB
compas_msgpack
139.7 KB
compas_msgpack_zstd
76.8 KB
10,000 elements
json
2.1 MB
json_zip
842.7 KB
compas_pb
1.0 MB
compas_pb_zip
503.6 KB
compas_pb_zstd
486.6 KB
compas_msgpack
1.4 MB
compas_msgpack_zstd
751.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json213.0 KB1.0×7.9 ms8.0 ms15.9 ms27.1261017.5 KB0✓ yes
1,000json_zip85.0 KB2.507×12.7 ms8.4 ms21.1 ms10.3141020.4 KB0✓ yes
1,000compas_pb106.5 KB2.001×6.9 ms11.5 ms18.4 ms9.447705.9 KB0✓ yes
1,000compas_pb_zip50.6 KB4.211×8.9 ms12.1 ms21.1 ms4.27813.6 KB0✓ yes
1,000compas_pb_zstd49.0 KB4.348×7.8 ms11.6 ms19.4 ms4.314812.4 KB0✓ yes
1,000compas_msgpack139.7 KB1.525×4.7 ms11.7 ms16.4 ms12.1751.6 MB0✓ yes
1,000compas_msgpack_zstd76.8 KB2.775×6.4 ms11.9 ms18.3 ms6.5821.7 MB0✓ yes
10,000json2.1 MB1.0×80.0 ms90.7 ms170.7 ms24.04610.0 MB0✓ yes
10,000json_zip842.7 KB2.528×123.0 ms98.3 ms221.3 ms8.77910.0 MB0✓ yes
10,000compas_pb1.0 MB2.001×72.2 ms127.4 ms199.6 ms8.5596.9 MB0✓ yes
10,000compas_pb_zip503.6 KB4.23×86.4 ms124.6 ms211.0 ms4.1398.0 MB0✓ yes
10,000compas_pb_zstd486.6 KB4.378×79.0 ms127.7 ms206.7 ms3.9028.0 MB0✓ yes
10,000compas_msgpack1.4 MB1.525×46.8 ms136.3 ms183.1 ms10.4916.1 MB0✓ yes
10,000compas_msgpack_zstd751.5 KB2.835×61.9 ms136.8 ms198.7 ms5.62317.4 MB0✓ yes

mesh

Round-trip time
1,000 elements
json
5.5 ms
json_zip
7.6 ms
compas_pb
5.2 ms
compas_pb_zip
5.8 ms
compas_pb_zstd
5.7 ms
compas_msgpack
8.2 ms
compas_msgpack_zstd
8.8 ms
10,000 elements
json
62.1 ms
json_zip
84.3 ms
compas_pb
53.2 ms
compas_pb_zip
60.4 ms
compas_pb_zstd
56.7 ms
compas_msgpack
94.8 ms
compas_msgpack_zstd
93.6 ms
Wire size
1,000 elements
json
80.2 KB
json_zip
27.4 KB
compas_pb
32.1 KB
compas_pb_zip
15.9 KB
compas_pb_zstd
15.8 KB
compas_msgpack
57.3 KB
compas_msgpack_zstd
24.5 KB
10,000 elements
json
864.1 KB
json_zip
238.2 KB
compas_pb
320.3 KB
compas_pb_zip
158.5 KB
compas_pb_zstd
168.6 KB
compas_msgpack
606.5 KB
compas_msgpack_zstd
198.8 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json80.2 KB1.0×1.8 ms3.7 ms5.5 ms21.961.5 MB0✓ yes
1,000json_zip27.4 KB2.928×3.8 ms3.8 ms7.6 ms7.3691.5 MB0✓ yes
1,000compas_pb32.1 KB2.496×1.9 ms3.4 ms5.2 ms9.784857.4 KB0✓ yes
1,000compas_pb_zip15.9 KB5.031×2.3 ms3.5 ms5.8 ms4.704890.9 KB0✓ yes
1,000compas_pb_zstd15.8 KB5.07×2.0 ms3.7 ms5.7 ms4.426889.6 KB0✓ yes
1,000compas_msgpack57.3 KB1.4×0.4 ms7.8 ms8.2 ms7.562.0 MB0✓ yes
1,000compas_msgpack_zstd24.5 KB3.269×1.0 ms7.7 ms8.8 ms3.2532.0 MB0✓ yes
10,000json864.1 KB1.0×16.4 ms45.7 ms62.1 ms19.37215.3 MB0✓ yes
10,000json_zip238.2 KB3.629×40.5 ms43.8 ms84.3 ms5.56615.3 MB0✓ yes
10,000compas_pb320.3 KB2.698×17.8 ms35.4 ms53.2 ms9.2568.3 MB0✓ yes
10,000compas_pb_zip158.5 KB5.453×23.9 ms36.5 ms60.4 ms4.4448.6 MB0✓ yes
10,000compas_pb_zstd168.6 KB5.125×21.0 ms35.7 ms56.7 ms4.8358.6 MB0✓ yes
10,000compas_msgpack606.5 KB1.425×4.5 ms90.3 ms94.8 ms6.87919.6 MB0✓ yes
10,000compas_msgpack_zstd198.8 KB4.348×7.8 ms85.8 ms93.6 ms2.37320.2 MB0✓ yes

mesh_attrs

Round-trip time
1,000 elements
json
5.6 ms
json_zip
8.5 ms
compas_pb
5.4 ms
compas_pb_zip
6.3 ms
compas_pb_zstd
5.7 ms
compas_msgpack
8.5 ms
compas_msgpack_zstd
9.3 ms
10,000 elements
json
65.7 ms
json_zip
94.0 ms
compas_pb
54.4 ms
compas_pb_zip
70.3 ms
compas_pb_zstd
57.4 ms
compas_msgpack
94.1 ms
compas_msgpack_zstd
103.5 ms
Wire size
1,000 elements
json
109.5 KB
json_zip
37.2 KB
compas_pb
40.2 KB
compas_pb_zip
23.7 KB
compas_pb_zstd
23.7 KB
compas_msgpack
74.3 KB
compas_msgpack_zstd
33.0 KB
10,000 elements
json
1.1 MB
json_zip
338.9 KB
compas_pb
398.5 KB
compas_pb_zip
232.9 KB
compas_pb_zstd
233.3 KB
compas_msgpack
772.5 KB
compas_msgpack_zstd
275.5 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json109.5 KB1.0×1.8 ms3.8 ms5.6 ms29.61.6 MB0✓ yes
1,000json_zip37.2 KB2.942×4.4 ms4.2 ms8.5 ms9.1411.6 MB0✓ yes
1,000compas_pb40.2 KB2.726×2.0 ms3.4 ms5.4 ms11.922945.2 KB0✓ yes
1,000compas_pb_zip23.7 KB4.611×2.7 ms3.5 ms6.3 ms6.858986.7 KB0✓ yes
1,000compas_pb_zstd23.7 KB4.617×2.3 ms3.4 ms5.7 ms7.055985.4 KB0✓ yes
1,000compas_msgpack74.3 KB1.474×0.4 ms8.0 ms8.5 ms9.4572.0 MB0✓ yes
1,000compas_msgpack_zstd33.0 KB3.317×1.3 ms8.0 ms9.3 ms4.22.1 MB0✓ yes
10,000json1.1 MB1.0×19.6 ms46.1 ms65.7 ms25.54415.8 MB0✓ yes
10,000json_zip338.9 KB3.393×47.3 ms46.7 ms94.0 ms7.43515.8 MB0✓ yes
10,000compas_pb398.5 KB2.886×19.9 ms34.5 ms54.4 ms11.8159.2 MB0✓ yes
10,000compas_pb_zip232.9 KB4.936×29.3 ms40.9 ms70.3 ms5.8299.5 MB0✓ yes
10,000compas_pb_zstd233.3 KB4.929×22.3 ms35.1 ms57.4 ms6.8099.5 MB0✓ yes
10,000compas_msgpack772.5 KB1.489×4.3 ms89.8 ms94.1 ms8.80819.9 MB0✓ yes
10,000compas_msgpack_zstd275.5 KB4.175×11.2 ms92.2 ms103.5 ms3.05820.6 MB0✓ yes

planes

Round-trip time
1,000 elements
json
13.9 ms
json_zip
18.6 ms
compas_pb
17.2 ms
compas_pb_zip
18.6 ms
compas_pb_zstd
17.9 ms
compas_msgpack
14.2 ms
compas_msgpack_zstd
15.9 ms
10,000 elements
json
150.9 ms
json_zip
196.7 ms
compas_pb
184.4 ms
compas_pb_zip
193.2 ms
compas_pb_zstd
185.5 ms
compas_msgpack
154.8 ms
compas_msgpack_zstd
175.7 ms
Wire size
1,000 elements
json
219.9 KB
json_zip
85.4 KB
compas_pb
107.4 KB
compas_pb_zip
51.1 KB
compas_pb_zstd
49.4 KB
compas_msgpack
143.6 KB
compas_msgpack_zstd
77.5 KB
10,000 elements
json
2.1 MB
json_zip
846.5 KB
compas_pb
1.0 MB
compas_pb_zip
508.5 KB
compas_pb_zstd
497.0 KB
compas_msgpack
1.4 MB
compas_msgpack_zstd
761.8 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json219.9 KB1.0×5.5 ms8.4 ms13.9 ms26.6811.0 MB2.2e-16✗ no
1,000json_zip85.4 KB2.576×9.9 ms8.7 ms18.6 ms10.0451.0 MB2.2e-16✗ no
1,000compas_pb107.4 KB2.046×4.8 ms12.4 ms17.2 ms8.849705.7 KB2.2e-16✗ no
1,000compas_pb_zip51.1 KB4.305×6.1 ms12.5 ms18.6 ms4.187814.4 KB2.2e-16✗ no
1,000compas_pb_zstd49.4 KB4.448×5.5 ms12.4 ms17.9 ms4.071813.2 KB2.2e-16✗ no
1,000compas_msgpack143.6 KB1.532×2.4 ms11.8 ms14.2 ms12.4161.6 MB2.2e-16✗ no
1,000compas_msgpack_zstd77.5 KB2.838×3.9 ms12.0 ms15.9 ms6.6241.7 MB2.2e-16✗ no
10,000json2.1 MB1.0×54.4 ms96.5 ms150.9 ms23.34310.0 MB2.2e-16✗ no
10,000json_zip846.5 KB2.598×98.4 ms98.3 ms196.7 ms8.81610.0 MB2.2e-16✗ no
10,000compas_pb1.0 MB2.047×49.2 ms135.2 ms184.4 ms8.1366.9 MB2.2e-16✗ no
10,000compas_pb_zip508.5 KB4.325×62.7 ms130.5 ms193.2 ms3.998.0 MB2.2e-16✗ no
10,000compas_pb_zstd497.0 KB4.425×54.7 ms130.8 ms185.5 ms3.8918.0 MB2.2e-16✗ no
10,000compas_msgpack1.4 MB1.532×23.7 ms131.1 ms154.8 ms11.21216.1 MB2.2e-16✗ no
10,000compas_msgpack_zstd761.8 KB2.887×37.7 ms138.1 ms175.7 ms5.65117.5 MB2.2e-16✗ no

pointcloud

Round-trip time
10,000 elements
json
26.9 ms
json_zip
50.3 ms
compas_pb
13.6 ms
compas_pb_zip
20.2 ms
compas_pb_zstd
14.1 ms
compas_msgpack
30.7 ms
compas_msgpack_zstd
32.6 ms
100,000 elements
json
342.3 ms
json_zip
539.8 ms
compas_pb
181.7 ms
compas_pb_zip
254.0 ms
compas_pb_zstd
191.5 ms
compas_msgpack
381.0 ms
compas_msgpack_zstd
434.1 ms
Wire size
10,000 elements
json
567.0 KB
json_zip
274.1 KB
compas_pb
234.4 KB
compas_pb_zip
223.4 KB
compas_pb_zstd
222.4 KB
compas_msgpack
273.5 KB
compas_msgpack_zstd
244.9 KB
100,000 elements
json
5.5 MB
json_zip
2.7 MB
compas_pb
2.3 MB
compas_pb_zip
2.2 MB
compas_pb_zstd
2.2 MB
compas_msgpack
2.7 MB
compas_msgpack_zstd
2.3 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
10,000json567.0 KB1.0×13.4 ms13.5 ms26.9 ms42.9214.1 MB0✓ yes
10,000json_zip274.1 KB2.068×35.6 ms14.7 ms50.3 ms19.0794.1 MB0✓ yes
10,000compas_pb234.4 KB2.419×3.1 ms10.6 ms13.6 ms22.7223.4 MB0✓ yes
10,000compas_pb_zip223.4 KB2.538×9.1 ms11.1 ms20.2 ms20.6683.7 MB0✓ yes
10,000compas_pb_zstd222.4 KB2.549×3.3 ms10.7 ms14.1 ms21.1953.7 MB0✓ yes
10,000compas_msgpack273.5 KB2.073×3.6 ms27.1 ms30.7 ms10.3374.4 MB0✓ yes
10,000compas_msgpack_zstd244.9 KB2.315×4.6 ms28.0 ms32.6 ms8.9684.6 MB0✓ yes
100,000json5.5 MB1.0×150.3 ms191.9 ms342.3 ms30.24240.6 MB0✓ yes
100,000json_zip2.7 MB2.079×352.1 ms187.7 ms539.8 ms14.87940.6 MB0✓ yes
100,000compas_pb2.3 MB2.419×30.6 ms151.1 ms181.7 ms15.88134.3 MB0✓ yes
100,000compas_pb_zip2.2 MB2.539×93.9 ms160.1 ms254.0 ms14.27736.6 MB0✓ yes
100,000compas_pb_zstd2.2 MB2.549×34.1 ms157.4 ms191.5 ms14.46936.6 MB0✓ yes
100,000compas_msgpack2.7 MB2.073×49.4 ms331.6 ms381.0 ms8.44343.5 MB0✓ yes
100,000compas_msgpack_zstd2.3 MB2.362×80.6 ms353.6 ms434.1 ms6.95146.2 MB0✓ yes

points

Round-trip time
1,000 elements
json
7.2 ms
json_zip
9.6 ms
compas_pb
8.0 ms
compas_pb_zip
8.9 ms
compas_pb_zstd
8.4 ms
compas_msgpack
6.8 ms
compas_msgpack_zstd
8.2 ms
10,000 elements
json
71.6 ms
json_zip
102.9 ms
compas_pb
79.9 ms
compas_pb_zip
90.8 ms
compas_pb_zstd
84.3 ms
compas_msgpack
77.7 ms
compas_msgpack_zstd
87.2 ms
Wire size
1,000 elements
json
141.7 KB
json_zip
54.7 KB
compas_pb
77.2 KB
compas_pb_zip
25.5 KB
compas_pb_zstd
24.4 KB
compas_msgpack
102.5 KB
compas_msgpack_zstd
50.6 KB
10,000 elements
json
1.4 MB
json_zip
539.8 KB
compas_pb
771.5 KB
compas_pb_zip
252.6 KB
compas_pb_zstd
241.6 KB
compas_msgpack
1.0 MB
compas_msgpack_zstd
499.4 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json141.7 KB1.0×3.5 ms3.7 ms7.2 ms39.354500.4 KB0✓ yes
1,000json_zip54.7 KB2.591×5.8 ms3.8 ms9.6 ms14.64502.9 KB0✓ yes
1,000compas_pb77.2 KB1.836×3.2 ms4.8 ms8.0 ms16.58260.1 KB0✓ yes
1,000compas_pb_zip25.5 KB5.559×4.0 ms4.9 ms8.9 ms5.321338.5 KB0✓ yes
1,000compas_pb_zstd24.4 KB5.812×3.7 ms4.8 ms8.4 ms5.217337.3 KB0✓ yes
1,000compas_msgpack102.5 KB1.382×1.7 ms5.2 ms6.8 ms20.344804.8 KB0✓ yes
1,000compas_msgpack_zstd50.6 KB2.797×2.8 ms5.3 ms8.2 ms9.745907.8 KB0✓ yes
10,000json1.4 MB1.0×35.0 ms36.6 ms71.6 ms39.5874.9 MB0✓ yes
10,000json_zip539.8 KB2.624×64.2 ms38.7 ms102.9 ms14.2874.9 MB0✓ yes
10,000compas_pb771.5 KB1.836×32.0 ms47.9 ms79.9 ms16.4822.6 MB0✓ yes
10,000compas_pb_zip252.6 KB5.609×40.6 ms50.2 ms90.8 ms5.1533.3 MB0✓ yes
10,000compas_pb_zstd241.6 KB5.863×35.9 ms48.3 ms84.3 ms5.1173.3 MB0✓ yes
10,000compas_msgpack1.0 MB1.381×16.6 ms61.1 ms77.7 ms17.1768.1 MB0✓ yes
10,000compas_msgpack_zstd499.4 KB2.836×26.9 ms60.3 ms87.2 ms8.4839.1 MB0✓ yes

polygons

Round-trip time
1,000 elements
json
30.0 ms
json_zip
41.6 ms
compas_pb
23.6 ms
compas_pb_zip
28.3 ms
compas_pb_zstd
26.4 ms
compas_msgpack
32.5 ms
compas_msgpack_zstd
34.8 ms
10,000 elements
json
323.5 ms
json_zip
446.9 ms
compas_pb
265.1 ms
compas_pb_zip
303.6 ms
compas_pb_zstd
280.2 ms
compas_msgpack
374.6 ms
compas_msgpack_zstd
402.3 ms
Wire size
1,000 elements
json
439.6 KB
json_zip
198.0 KB
compas_pb
199.2 KB
compas_pb_zip
136.2 KB
compas_pb_zstd
134.9 KB
compas_msgpack
250.0 KB
compas_msgpack_zstd
174.0 KB
10,000 elements
json
4.3 MB
json_zip
1.9 MB
compas_pb
1.9 MB
compas_pb_zip
1.3 MB
compas_pb_zstd
1.3 MB
compas_msgpack
2.4 MB
compas_msgpack_zstd
1.7 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json439.6 KB1.0×10.9 ms19.2 ms30.0 ms23.5012.4 MB0✓ yes
1,000json_zip198.0 KB2.221×22.6 ms19.0 ms41.6 ms10.6792.4 MB0✓ yes
1,000compas_pb199.2 KB2.206×5.3 ms18.3 ms23.6 ms11.1351.9 MB0✓ yes
1,000compas_pb_zip136.2 KB3.229×8.9 ms19.4 ms28.3 ms7.1872.1 MB0✓ yes
1,000compas_pb_zstd134.9 KB3.258×6.6 ms19.8 ms26.4 ms6.9782.1 MB0✓ yes
1,000compas_msgpack250.0 KB1.758×3.9 ms28.5 ms32.5 ms8.9683.2 MB0✓ yes
1,000compas_msgpack_zstd174.0 KB2.526×6.7 ms28.1 ms34.8 ms6.3433.4 MB0✓ yes
10,000json4.3 MB1.0×113.0 ms210.5 ms323.5 ms21.38924.5 MB0✓ yes
10,000json_zip1.9 MB2.233×228.2 ms218.8 ms446.9 ms9.2224.5 MB0✓ yes
10,000compas_pb1.9 MB2.207×54.8 ms210.3 ms265.1 ms9.719.2 MB0✓ yes
10,000compas_pb_zip1.3 MB3.234×91.2 ms212.4 ms303.6 ms6.55521.2 MB0✓ yes
10,000compas_pb_zstd1.3 MB3.268×68.5 ms211.7 ms280.2 ms6.50921.2 MB0✓ yes
10,000compas_msgpack2.4 MB1.759×37.2 ms337.4 ms374.6 ms7.58731.7 MB0✓ yes
10,000compas_msgpack_zstd1.7 MB2.51×62.3 ms340.0 ms402.3 ms5.27634.2 MB0✓ yes

polyhedrons

Round-trip time
1,000 elements
json
14.0 ms
json_zip
22.3 ms
compas_pb
15.9 ms
compas_pb_zip
18.4 ms
compas_pb_zstd
17.0 ms
compas_msgpack
21.8 ms
compas_msgpack_zstd
24.1 ms
10,000 elements
json
167.9 ms
json_zip
255.7 ms
compas_pb
185.3 ms
compas_pb_zip
210.5 ms
compas_pb_zstd
195.2 ms
compas_msgpack
280.6 ms
compas_msgpack_zstd
302.6 ms
Wire size
1,000 elements
json
372.3 KB
json_zip
143.5 KB
compas_pb
180.7 KB
compas_pb_zip
91.5 KB
compas_pb_zstd
90.3 KB
compas_msgpack
222.7 KB
compas_msgpack_zstd
126.2 KB
10,000 elements
json
3.6 MB
json_zip
1.4 MB
compas_pb
1.8 MB
compas_pb_zip
912.9 KB
compas_pb_zstd
907.3 KB
compas_msgpack
2.2 MB
compas_msgpack_zstd
1.2 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json372.3 KB1.0×7.7 ms6.3 ms14.0 ms60.2181.8 MB0✓ yes
1,000json_zip143.5 KB2.595×15.3 ms7.0 ms22.3 ms20.9681.8 MB0✓ yes
1,000compas_pb180.7 KB2.06×7.8 ms8.1 ms15.9 ms22.721.2 MB0✓ yes
1,000compas_pb_zip91.5 KB4.069×9.8 ms8.7 ms18.4 ms10.8081.4 MB0✓ yes
1,000compas_pb_zstd90.3 KB4.123×8.7 ms8.2 ms17.0 ms11.2281.4 MB0✓ yes
1,000compas_msgpack222.7 KB1.672×1.7 ms20.1 ms21.8 ms11.3532.8 MB0✓ yes
1,000compas_msgpack_zstd126.2 KB2.95×3.8 ms20.3 ms24.1 ms6.3663.0 MB0✓ yes
10,000json3.6 MB1.0×78.1 ms89.7 ms167.9 ms42.48517.6 MB0✓ yes
10,000json_zip1.4 MB2.609×151.7 ms104.1 ms255.7 ms14.04117.6 MB0✓ yes
10,000compas_pb1.8 MB2.061×78.9 ms106.4 ms185.3 ms17.38412.4 MB0✓ yes
10,000compas_pb_zip912.9 KB4.078×100.0 ms110.5 ms210.5 ms8.46114.2 MB0✓ yes
10,000compas_pb_zstd907.3 KB4.103×87.8 ms107.5 ms195.2 ms8.64614.2 MB0✓ yes
10,000compas_msgpack2.2 MB1.672×17.1 ms263.5 ms280.6 ms8.65127.8 MB0✓ yes
10,000compas_msgpack_zstd1.2 MB2.946×35.4 ms267.3 ms302.6 ms4.84130.0 MB0✓ yes

polylines

Round-trip time
1,000 elements
json
28.7 ms
json_zip
45.1 ms
compas_pb
20.1 ms
compas_pb_zip
25.4 ms
compas_pb_zstd
22.6 ms
compas_msgpack
31.5 ms
compas_msgpack_zstd
34.3 ms
10,000 elements
json
319.9 ms
json_zip
493.7 ms
compas_pb
230.2 ms
compas_pb_zip
289.2 ms
compas_pb_zstd
249.1 ms
compas_msgpack
384.9 ms
compas_msgpack_zstd
425.2 ms
Wire size
1,000 elements
json
554.0 KB
json_zip
253.4 KB
compas_pb
247.1 KB
compas_pb_zip
180.9 KB
compas_pb_zstd
179.5 KB
compas_msgpack
305.7 KB
compas_msgpack_zstd
228.6 KB
10,000 elements
json
5.4 MB
json_zip
2.5 MB
compas_pb
2.4 MB
compas_pb_zip
1.8 MB
compas_pb_zstd
1.7 MB
compas_msgpack
3.0 MB
compas_msgpack_zstd
2.2 MB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json554.0 KB1.0×13.5 ms15.2 ms28.7 ms37.4162.9 MB0✓ yes
1,000json_zip253.4 KB2.186×29.3 ms15.9 ms45.1 ms16.3483.0 MB0✓ yes
1,000compas_pb247.1 KB2.242×5.9 ms14.2 ms20.1 ms17.8752.3 MB0✓ yes
1,000compas_pb_zip180.9 KB3.063×10.6 ms14.7 ms25.4 ms12.5852.6 MB0✓ yes
1,000compas_pb_zstd179.5 KB3.087×7.6 ms15.0 ms22.6 ms12.292.6 MB0✓ yes
1,000compas_msgpack305.7 KB1.813×4.4 ms27.1 ms31.5 ms11.5683.7 MB0✓ yes
1,000compas_msgpack_zstd228.6 KB2.423×6.5 ms27.8 ms34.3 ms8.424.0 MB0✓ yes
10,000json5.4 MB1.0×139.8 ms180.1 ms319.9 ms31.50729.6 MB0✓ yes
10,000json_zip2.5 MB2.195×302.8 ms190.9 ms493.7 ms13.53929.6 MB0✓ yes
10,000compas_pb2.4 MB2.243×62.1 ms168.1 ms230.2 ms15.04923.2 MB0✓ yes
10,000compas_pb_zip1.8 MB3.066×109.2 ms180.0 ms289.2 ms10.2825.6 MB0✓ yes
10,000compas_pb_zstd1.7 MB3.095×77.3 ms171.8 ms249.1 ms10.67425.6 MB0✓ yes
10,000compas_msgpack3.0 MB1.813×44.4 ms340.5 ms384.9 ms9.19337.4 MB0✓ yes
10,000compas_msgpack_zstd2.2 MB2.478×74.1 ms351.1 ms425.2 ms6.52140.4 MB0✓ yes

spheres

Round-trip time
1,000 elements
json
44.1 ms
json_zip
47.6 ms
compas_pb
51.4 ms
compas_pb_zip
52.0 ms
compas_pb_zstd
51.4 ms
compas_msgpack
47.2 ms
compas_msgpack_zstd
49.0 ms
10,000 elements
json
461.6 ms
json_zip
496.5 ms
compas_pb
516.6 ms
compas_pb_zip
534.8 ms
compas_pb_zstd
530.8 ms
compas_msgpack
510.0 ms
compas_msgpack_zstd
523.4 ms
Wire size
1,000 elements
json
231.7 KB
json_zip
66.7 KB
compas_pb
112.3 KB
compas_pb_zip
34.3 KB
compas_pb_zstd
32.4 KB
compas_msgpack
199.2 KB
compas_msgpack_zstd
60.8 KB
10,000 elements
json
2.3 MB
json_zip
661.5 KB
compas_pb
1.1 MB
compas_pb_zip
340.4 KB
compas_pb_zstd
326.9 KB
compas_msgpack
1.9 MB
compas_msgpack_zstd
594.8 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json231.7 KB1.0×6.5 ms37.6 ms44.1 ms6.3091.6 MB0✓ yes
1,000json_zip66.7 KB3.471×9.3 ms38.4 ms47.6 ms1.7811.6 MB0✓ yes
1,000compas_pb112.3 KB2.063×6.3 ms45.0 ms51.4 ms2.5541.2 MB0✓ yes
1,000compas_pb_zip34.3 KB6.756×7.7 ms44.4 ms52.0 ms0.7921.3 MB0✓ yes
1,000compas_pb_zstd32.4 KB7.145×7.2 ms44.1 ms51.4 ms0.7521.3 MB0✓ yes
1,000compas_msgpack199.2 KB1.163×3.1 ms44.1 ms47.2 ms4.6262.5 MB0✓ yes
1,000compas_msgpack_zstd60.8 KB3.813×4.7 ms44.3 ms49.0 ms1.4042.7 MB0✓ yes
10,000json2.3 MB1.0×65.4 ms396.2 ms461.6 ms5.98815.6 MB0✓ yes
10,000json_zip661.5 KB3.502×95.1 ms401.4 ms496.5 ms1.68815.6 MB0✓ yes
10,000compas_pb1.1 MB2.063×63.5 ms453.1 ms516.6 ms2.53812.4 MB0✓ yes
10,000compas_pb_zip340.4 KB6.805×75.0 ms459.7 ms534.8 ms0.75813.5 MB0✓ yes
10,000compas_pb_zstd326.9 KB7.086×72.5 ms458.3 ms530.8 ms0.7313.5 MB0✓ yes
10,000compas_msgpack1.9 MB1.163×33.6 ms476.4 ms510.0 ms4.28325.2 MB0✓ yes
10,000compas_msgpack_zstd594.8 KB3.895×46.6 ms476.7 ms523.4 ms1.27827.1 MB0✓ yes

transformations

Round-trip time
1,000 elements
json
11.9 ms
json_zip
14.6 ms
compas_pb
12.5 ms
compas_pb_zip
13.4 ms
compas_pb_zstd
13.5 ms
compas_msgpack
15.9 ms
compas_msgpack_zstd
16.5 ms
10,000 elements
json
133.2 ms
json_zip
156.4 ms
compas_pb
156.2 ms
compas_pb_zip
144.7 ms
compas_pb_zstd
147.4 ms
compas_msgpack
184.8 ms
compas_msgpack_zstd
211.8 ms
Wire size
1,000 elements
json
342.8 KB
json_zip
59.9 KB
compas_pb
190.4 KB
compas_pb_zip
27.3 KB
compas_pb_zstd
23.6 KB
compas_msgpack
237.3 KB
compas_msgpack_zstd
51.7 KB
10,000 elements
json
3.3 MB
json_zip
594.4 KB
compas_pb
1.9 MB
compas_pb_zip
269.7 KB
compas_pb_zstd
244.5 KB
compas_msgpack
2.3 MB
compas_msgpack_zstd
503.1 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json342.8 KB1.0×6.6 ms5.3 ms11.9 ms66.221.4 MB0✓ yes
1,000json_zip59.9 KB5.727×9.4 ms5.1 ms14.6 ms11.9211.4 MB0✓ yes
1,000compas_pb190.4 KB1.8×5.5 ms7.0 ms12.5 ms28.019951.1 KB0✓ yes
1,000compas_pb_zip27.3 KB12.551×6.6 ms6.8 ms13.4 ms4.1161.1 MB0✓ yes
1,000compas_pb_zstd23.6 KB14.55×6.8 ms6.7 ms13.5 ms3.6151.1 MB0✓ yes
1,000compas_msgpack237.3 KB1.445×1.5 ms14.5 ms15.9 ms16.7922.0 MB0✓ yes
1,000compas_msgpack_zstd51.7 KB6.635×3.2 ms13.3 ms16.5 ms3.9782.3 MB0✓ yes
10,000json3.3 MB1.0×68.0 ms65.3 ms133.2 ms53.78113.7 MB0✓ yes
10,000json_zip594.4 KB5.767×91.9 ms64.5 ms156.4 ms9.44213.7 MB0✓ yes
10,000compas_pb1.9 MB1.8×61.0 ms95.2 ms156.2 ms20.4899.4 MB0✓ yes
10,000compas_pb_zip269.7 KB12.712×65.3 ms79.4 ms144.7 ms3.47811.2 MB0✓ yes
10,000compas_pb_zstd244.5 KB14.023×70.1 ms77.3 ms147.4 ms3.23811.2 MB0✓ yes
10,000compas_msgpack2.3 MB1.445×15.0 ms169.9 ms184.8 ms14.30620.6 MB0✓ yes
10,000compas_msgpack_zstd503.1 KB6.814×31.1 ms180.7 ms211.8 ms2.85122.9 MB0✓ yes

vectors

Round-trip time
1,000 elements
json
7.3 ms
json_zip
9.8 ms
compas_pb
8.2 ms
compas_pb_zip
8.9 ms
compas_pb_zstd
8.8 ms
compas_msgpack
7.3 ms
compas_msgpack_zstd
8.8 ms
10,000 elements
json
74.7 ms
json_zip
104.4 ms
compas_pb
87.1 ms
compas_pb_zip
91.2 ms
compas_pb_zstd
86.9 ms
compas_msgpack
72.5 ms
compas_msgpack_zstd
86.2 ms
Wire size
1,000 elements
json
142.6 KB
json_zip
54.6 KB
compas_pb
78.1 KB
compas_pb_zip
25.5 KB
compas_pb_zstd
24.4 KB
compas_msgpack
103.5 KB
compas_msgpack_zstd
50.6 KB
10,000 elements
json
1.4 MB
json_zip
540.0 KB
compas_pb
781.3 KB
compas_pb_zip
252.6 KB
compas_pb_zstd
244.1 KB
compas_msgpack
1.0 MB
compas_msgpack_zstd
495.1 KB
sizeformatwire sizevs JSONdumploadround-tripload MB/speak memmax errlossless
1,000json142.6 KB1.0×3.5 ms3.8 ms7.3 ms38.482501.8 KB0✓ yes
1,000json_zip54.6 KB2.613×5.8 ms4.0 ms9.8 ms13.894504.2 KB0✓ yes
1,000compas_pb78.1 KB1.826×3.3 ms4.9 ms8.2 ms16.296260.1 KB0✓ yes
1,000compas_pb_zip25.5 KB5.597×3.9 ms5.1 ms8.9 ms5.156339.4 KB0✓ yes
1,000compas_pb_zstd24.4 KB5.852×3.8 ms5.1 ms8.8 ms4.926338.3 KB0✓ yes
1,000compas_msgpack103.5 KB1.378×1.7 ms5.6 ms7.3 ms18.858805.7 KB0✓ yes
1,000compas_msgpack_zstd50.6 KB2.819×2.9 ms5.9 ms8.8 ms8.733909.3 KB0✓ yes
10,000json1.4 MB1.0×35.6 ms39.2 ms74.7 ms37.34.9 MB0✓ yes
10,000json_zip540.0 KB2.641×61.5 ms42.9 ms104.4 ms12.8914.9 MB0✓ yes
10,000compas_pb781.3 KB1.826×34.9 ms52.2 ms87.1 ms15.3272.6 MB0✓ yes
10,000compas_pb_zip252.6 KB5.647×39.8 ms51.4 ms91.2 ms5.0313.4 MB0✓ yes
10,000compas_pb_zstd244.1 KB5.842×36.8 ms50.1 ms86.9 ms4.993.4 MB0✓ yes
10,000compas_msgpack1.0 MB1.378×16.8 ms55.7 ms72.5 ms19.0218.1 MB0✓ yes
10,000compas_msgpack_zstd495.1 KB2.881×26.3 ms59.9 ms86.2 ms8.479.1 MB0✓ yes