Skip to content

table: let a table message hold messages that have no table - #475

Draft
iainmcgin wants to merge 11 commits into
table-codegenfrom
table-bridge
Draft

iainmcgin wants to merge 11 commits into
table-codegenfrom
table-bridge

Conversation

@iainmcgin

Copy link
Copy Markdown
Collaborator

Message fields of a table message can now hold messages that have no table: unrolled ones, extern_path types, and well-known types. On whatsapp.proto (752 messages, Box fields, fat LTO), the text section at opt-level = "z" is 1,669,507 bytes unrolled, 1,236,115 with CodecStrategy::Table on #469, and 1,009,611 here; table messages go from 636 to 709 of 752, because 73 of the 116 that fell back on #469 only held a message with a oneof or map, and 43 have one. The guide has the s and 3 figures.

A field's descriptor holds the child's table or a DynVt, function pointers that call the child's Message impl. MsgVt::new_via_message and RepVt::new_via_message are new const fns in buffa::table; a child reached this way decodes from the slice of the nearest enclosing table message, so an overrun fails at that message's end.

Differences from #469:

  • A message holding, transitively and through any field kind, a message of the run with a non-default bytes type stays unrolled, because the table decodes a contiguous &[u8] and would copy the Bytes fields. Another crate's child is not inspected, so a holder of google.protobuf.Any (value is Bytes) keeps its table and copies the payload.
  • The DynVt write function takes the PreSized cursor that Message::encode uses for every BufMut. Any other sink, including a BufMut passed to Message::write_to, gets each child from a scratch Vec; a Rope copies again.

Instructions per call against all unrolled: a table parent with nine unrolled children is +6.5% to size, +7.3% to encode, +6.5% to decode; a table message of two Timestamp fields is +54%, +41%, +31%. Table-to-table fields cost 0.3% to 1.2% more than on #469.

The unsafe in table/bridge.rs is three thunks that cast *const u8 back to the child type, and the Child methods forwarding to them.

… wording

A table message that holds a message of another crate with a bytes field,
such as google.protobuf.Any, copies the field on decode. Say so in the
CodecStrategy::Table docs, the guide, DESIGN.md and the runtime docs, and
point at the guide for the measurements. Correct the bridge module docs
(dangling list, renamed constructors, Rope copy), qualify the size claim,
drop the fallback warning's claim that a fallback is larger, and shorten
the changelog fragment to a user-level summary.
…ested bytes

Add codegen tests for a holder declared before the message it holds, cycles
with and without a bytes field, repeated bytes, map values, the bytes-key
carve-out and a nested message. Add buffa-test checks that the messages set
to unrolled really have no table, and a test that pins the copy of an Any
payload.
@github-actions

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant