{% set rfcid = “RFC-0113” %} {% include “docs/contribute/governance/rfcs/_common/_rfc_header.md” %}
Note: This is a resubmission of the previously rejected RFC-0032.
“Turning Envelopes into Postcards”
This RFC proposes a more compact encoding for FIDL[^1].
Envelopes are the foundation for extensible, evolvable data structures (tables and extensible unions). A more compact and efficient wire format for envelopes enables those extensible structures to be used in more contexts where performance and wire size matter.
The proposed envelope format can be described as the following C-struct:
struct Envelope { uint32_t byte_size; uint32_t handle_count; };
Compared with the existing envelope format:
vector<string>
includes the size of the outer vector's inner string sub-objects.FIDL_ALLOC_ABSENT
.Decoders MAY overwrite the envelope with a pointer to the envelope data, assuming they know the static type (schema) of the envelope‘s contents. See the Unknown Data section for recommendations on how to process an envelope if the content’s type is unknown.
The encoded or decoded form of an envelope can be described as a C-union:
typedef union { struct { uint32_t byte_size; uint32_t handle_count; } encoded; void* data; } fidl_envelope_t; static_assert(sizeof(fidl_envelope_t) == sizeof(void*));
Receivers — validators & decoders — may not know the type of an envelope when they‘re used in an evolvable data structure. If a receiver doesn’t know the type, an envelope can be minimally parsed and skipped.
This RFC is a breaking wire format change.
A complex wire format migration will be undertaken to switch to efficient envelopes. This wire format change will be combined with other migrations to reduce the per-feature migration cost.
The proposed wire format change is API (source) compatible. Any hand-rolled FIDL code would need to be updated to handle the new wire format.
The wire format change is ABI-incompatible.
A performance evaluation was run in a CL that prototypes an efficient envelope implementation. For this test, the input was a table with all fields set. Other inputs produced similar results.
The following times are in nanoseconds. The time without efficient envelopes is before the arrow and the time with efficient envelopes is after the arrow.
# Fields | Encode | Decode |
---|---|---|
16 | 64 -> 40 | 176 -> 146 |
64 | 165 -> 121 | 321 -> 221 |
256 | 567 -> 368 | 923 -> 527 |
1024 | 2139 -> 1429 | 3284 -> 1636 |
Depending on the input, using efficient envelopes appears to be 1.1-2x faster
There should not be any security implications from this RFC.
One minor security advantage is that this RFC removes information that is otherwise duplicated in the size and pointer in the old format. Previously, an envelope may be received with non-zero size/handles and FIDL_ALLOC_ABSENT
, or zero size/handles and FIDL_ALLOC_PRESENT
. This required extra validation checks, which will no longer be needed.
It is not possible to determine if an envelope is in wire form or decoded form off of the data alone. This is not a problem because in practice there is always separate bookkeeping in bindings that keeps track of whether the message is in wire form or decoded form.
There should not be any privacy implications from this RFC.
We can keep the existing wire format if we believe the efficiency gains in this proposal are not worth the implementation cost.
This RFC was previously rejected with the following rationale (copied here verbatim) before being resubmitted for review:
In February 21, 2019, this RFC was initially accepted. The FIDL team worked to stabilize the wire format for most of 2019, culminating in an all-hands-on-deck effort which spanned Q3 and Q4. The migration completed on Dec 1st, 2019.
The stabilization effort spanned multiple changes:
- Major RFC-0061: Extensible Unions
- [RFC-0032: Efficient Envelopes] (0032_efficient_envelopes.md), i.e. this RFC
- [RFC-0037: Transactional Message Header v3] (0037_transactional_message_header_v3.md)
- RFC-0048: Explicit Union Ordinals
However, as the work unfolded, and the Dec 1st deadline loomed, the FIDL team decided to punt on implementing the efficient envelopes change, preferring to push this work to 2020. Unlike the other changes which were part of the stabilization effort, efficient envelopes was simply an in-memory size saving, which was very small, especially when compared to other aspects of the FIDL wire format (e.g. tables' dense format). Deferring was a project risk reduction calculation, by reducing the scope, the odds of completing all the work on time were improved. So was the FIDL team's work schedule.
We're now close to 18 months after the deferral, and efficient envelopes are long forgotten. Significant performance work in 2020 demonstrated that this change would have no material impact.
It‘s time to face the truth, this ain’t going to happen. Rejected.
The FIDL team is currently planning to batch together several wire format changes and undergo a migration with all of them at once. This means there is opportunity to add support for efficient envelopes in a lower cost way (in that the cost is shared with other migrations).
Additionally, there are now concrete numbers for the performance gains due to efficient envelopes and the gains are significant.
Because of these factors, this is an opportune time to resurrect this RFC and implement it.
This RFC is a slimmed-down version of rfc-0026, which was rejected since there wasn't enough consensus around the whole RFC.
[^1]: This RFC is based on rfc-0026, but with only the out-of-line envelope proposal. Inlining, envelopes everywhere, and moving the string/vector count out-of-line, have all been removed.