docs: add arrow to the well-known encodings registry#1748
Draft
amacneil wants to merge 6 commits into
Draft
Conversation
Co-authored-by: Adrian Macneil <adrian@foxglove.dev>
Co-authored-by: Adrian Macneil <adrian@foxglove.dev>
…on, and timestamp semantics Co-authored-by: Adrian Macneil <adrian@foxglove.dev>
Co-authored-by: Adrian Macneil <adrian@foxglove.dev>
Co-authored-by: Adrian Macneil <adrian@foxglove.dev>
Co-authored-by: Adrian Macneil <adrian@foxglove.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Apache Arrow as a well-known message encoding and schema encoding in the format registry.
arrow: each message is a single Arrow IPC encapsulatedRecordBatchconforming to the channel's schema. The schema lives in the Schema record (not repeated per message), columns must not be dictionary-encoded so everyRecordBatchdecodes independently, and bodies must not use Arrow body compression (use Chunk compression instead) — mirroring howprotobuf/flatbufferkeep the descriptor in the Schema record and a bare payload in each message.arrow: the schemadatais a serialized Arrow IPCSchemamessage.The registry text is kept terse and format-only, consistent with the existing entries; motivation and rationale are below rather than in the spec.
Motivation
Arrow is a stable, language-neutral columnar format with a well-specified IPC representation, and it's a natural fit for MCAP's "arbitrary serialization format" model. Standardizing a single
arrowencoding lets us build one decode path that serves several increasingly common conversion sources:RecordBatches directly.RecordBatches (Parquet isn't shardable into self-contained per-message units, so storing as Arrow is the clean target), then store with the samearrowencoding..rrdfiles — Rerun stores Arrow record batches internally, so they decode into the samearrowrepresentation.Establishing the registry convention is the prerequisite for a future
mcap convertpath from these formats (with the source's chosen timestamp column/timeline mapped to each message'slog_time) and formcap catdecoding support. This PR is docs-only and intentionally scoped to the registry entries.Alternatives considered
The central decision is what
Message.dataholds. We chose exactly one bare encapsulatedRecordBatch, with the schema stored once in the Schema record. Alternatives we weighed:RecordBatch). This is how Rerun'sArrowMsgis shaped, and it has the appeal of being self-describing and usable via the high-levelStreamWriter/StreamReaderAPIs. Rejected because it repeats the schema in every message — measured at ~130 B for a tiny schema up to a few KB for wide/nested ones, which roughly doubles a single-row message (largely recovered by Chunk compression since the bytes are identical, but still a per-message CPU cost) — and it makes the Schema record redundant/optional, degradingmcap list schemas/mcap info. Keeping the schema in the Schema record mirrorsprotobuf/flatbuffer.RecordBatch." Rejected as under-specified: it leaves open whether multipleRecordBatches,DictionaryBatches, or an embedded schema may appear, and what wins if an embedded schema disagrees with the Schema record. Those are exactly the interop forks a registry entry should remove. If a self-describing form is ever wanted, it should be pinned precisely ("a complete stream with a schema and exactly oneRecordBatch") rather than left open-ended.RecordBatchcan't carry the precedingDictionaryBatchit would need, and dictionary IDs are stream-ordered state that is fragile under MCAP's random access, merge, filter, and sort. Converters hydrate dictionary columns to their value type on the way in (values preserved, only the encoding dropped). The rule covers nested fields (structs, lists, maps, unions), not just top-level columns.BodyCompression). Disallowed. It would double-compress on top of MCAP Chunk compression and force every reader to implement Arrow per-buffer LZ4/ZSTD; Chunk compression already covers size.Tensor/SparseTensor. Out of scope. StandaloneTensor/SparseTensoraren't part of the IPC file/stream format; tensor data that appears as extension-typed columns inside aRecordBatch(arrow.fixed_shape_tensor, etc.) is already supported since we store the schema and batch verbatim.RecordBatchto contain one or more rows; MCAP treats the whole batch as occurring at the message'slog_time. A converter can default to one row per message (most faithful to MCAP-native, per-message time semantics) and offer batching as an opt-in size/throughput trade-off.Net: the single-
RecordBatchform is the leanest, has the simplest decode path (read_record_batch(data, schema)), keeps crisp one-message/one-log_timesemantics, stays robust under the CLI's reorder/merge/filter/sort operations, and matches the existing registry entries.Notes
IPC,pyarrow, andstructsto the cspell word list so the spell-check CI passes.Schema.dataandMessage.dataas opaque bytes, so this entry is purely a documented convention.