pw_protobuf extended size report#

pw_protobuf can impact binary size very differently depending on how it’s used. A series of examples are provided below to illustrate how much certain use cases affect binary size.

Overview#

This module includes a proto encoder, two different proto decoders (one that operates on a pw::stream::StreamReader and another that operates on an in- memory buffer), codegen for direct wire-format encoders/decoders, and a table-based codegen system for constructing proto messages as in-memory structs.

Here’s a brief overview of the different encoder/decoder costs:

Label

Segment

Delta

Full wire-format proto encode/decode library

FLASH

-4

[section .code]

NEW

+824

pw::protobuf::StreamDecoder::ReadRepeatedFixedField<>()

NEW

+730

pw::protobuf::StreamDecoder::ReadRepeatedVarintField<>()

NEW

+614

pw::protobuf::StreamEncoder::WritePackedVarints<>()

NEW

+240

pw::protobuf::StreamDecoder::ReadFieldKey()

NEW

+228

pw::protobuf::StreamDecoder::ReadOneVarint()

NEW

+208

pw::protobuf::StreamEncoder::WriteLengthDelimitedFieldFromStream()

NEW

+196

pw::protobuf::StreamEncoder::GetNestedEncoder()

NEW

+192

pw::protobuf::StreamEncoder::WritePackedFixed()

NEW

+172

pw::protobuf::StreamDecoder::ReadPackedVarintField()

NEW

+168

pw::protobuf::StreamDecoder::SkipField()

NEW

+144

pw::protobuf::Decoder::FieldSize()

NEW

+124

pw::protobuf::StreamEncoder::CloseNestedMessage()

NEW

+116

pw::protobuf::StreamEncoder::UpdateStatusForWrite()

NEW

+110

pw::protobuf::StreamDecoder::ReadPackedFixedField()

NEW

+104

pw::protobuf::StreamDecoder::ReadDelimitedField()

NEW

+100

pw::protobuf::StreamDecoder::ReadVarintField<>()

NEW

+98

pw::protobuf::StreamDecoder::ReadFixedField()

NEW

+96

pw::protobuf::Decoder::ReadDelimited()

NEW

+96

pw::protobuf::StreamDecoder::GetBytesReader()

NEW

+96

pw::protobuf::StreamDecoder::ReadVarintField()

NEW

+90

pw::protobuf::StreamDecoder::Advance()

NEW

+88

pw::protobuf::Decoder::ConsumeKey()

NEW

+88

pw::protobuf::StreamDecoder::BytesReader::DoSeek()

NEW

+88

pw::protobuf::StreamDecoder::CloseNestedDecoder()

NEW

+88

pw::protobuf::StreamEncoder::WriteFixed()

NEW

+80

pw::protobuf::StreamDecoder::Next()

NEW

+76

pw::protobuf::StreamEncoder::WriteVarintField()

NEW

+74

pw::protobuf::Decoder::ReadFixed()

NEW

+74

pw::protobuf::StreamDecoder::BytesReader::DoRead()

NEW

+70

pw::protobuf::FieldKey::FieldKey()

NEW

+68

pw::protobuf::StreamEncoder::WriteLengthDelimitedField()

NEW

+68

pw::protobuf::StreamEncoder::WriteVarint()

NEW

+64

pw::protobuf::StreamDecoder::CheckOkToRead()

NEW

+60

pw::protobuf::FieldKey::IsValidKey()

NEW

+60

pw::protobuf::StreamDecoder::~StreamDecoder()

NEW

+58

pw::protobuf::Decoder::ReadVarint()

NEW

+54

pw::protobuf::Decoder::SkipField()

NEW

+54

pw::protobuf::StreamEncoder::WriteFloat()

NEW

+52

pw::protobuf::Decoder::ReadUint32()

NEW

+50

pw::protobuf::Decoder::ReadSint32()

NEW

+50

pw::protobuf::Decoder::ReadSint64()

NEW

+48

pw::protobuf::StreamEncoder::CloseEncoder()

NEW

+48

pw::protobuf::StreamEncoder::WriteFixed32()

NEW

+46

pw::protobuf::Decoder::Next()

NEW

+46

pw::protobuf::WriteVarint()

NEW

+44

pw::protobuf::StreamDecoder::BytesReader::~BytesReader()

NEW

+44

pw::protobuf::StreamDecoder::CloseBytesReader()

NEW

+44

pw::protobuf::WriteLengthDelimitedKeyAndLengthPrefix()

NEW

+40

pw::protobuf::Decoder::ReadBool()

NEW

+40

pw::protobuf::StreamEncoder::WriteFixed64()

NEW

+38

pw::protobuf::StreamDecoder::GetLengthDelimitedPayloadBounds()

NEW

+36

pw::protobuf::Decoder::FieldNumber()

NEW

+36

pw::protobuf::StreamDecoder::BytesReader

NEW

+32

pw::protobuf::Decoder::ReadString()

NEW

+32

pw::protobuf::ValidFieldNumber()

NEW

+28

pw::protobuf::TagSizeBytes<>()

+6,708

Including table-based Message encoder and decoder

FLASH

-4

[section .code]

NEW

+1,228

pw::protobuf::StreamEncoder::Write()

NEW

+1,060

pw::protobuf::StreamDecoder::Read()

NEW

+824

pw::protobuf::StreamDecoder::ReadRepeatedFixedField<>()

NEW

+730

pw::protobuf::StreamDecoder::ReadRepeatedVarintField<>()

NEW

+614

pw::protobuf::StreamEncoder::WritePackedVarints<>()

NEW

+240

pw::protobuf::StreamDecoder::ReadFieldKey()

NEW

+228

pw::protobuf::StreamDecoder::ReadOneVarint()

NEW

+208

pw::protobuf::StreamEncoder::WriteLengthDelimitedFieldFromStream()

NEW

+196

pw::protobuf::StreamEncoder::GetNestedEncoder()

NEW

+192

pw::protobuf::StreamEncoder::WritePackedFixed()

NEW

+172

pw::protobuf::StreamDecoder::ReadPackedVarintField()

NEW

+168

pw::protobuf::StreamDecoder::SkipField()

NEW

+144

pw::protobuf::Decoder::FieldSize()

NEW

+124

pw::protobuf::StreamEncoder::CloseNestedMessage()

NEW

+116

pw::protobuf::StreamDecoder::GetNestedDecoder()

NEW

+116

pw::protobuf::StreamEncoder::UpdateStatusForWrite()

NEW

+110

pw::protobuf::StreamDecoder::ReadPackedFixedField()

NEW

+104

pw::protobuf::StreamDecoder::ReadDelimitedField()

NEW

+100

pw::protobuf::StreamDecoder::ReadVarintField<>()

NEW

+98

pw::protobuf::StreamDecoder::ReadFixedField()

NEW

+96

pw::protobuf::Decoder::ReadDelimited()

NEW

+96

pw::protobuf::StreamDecoder::GetBytesReader()

NEW

+96

pw::protobuf::StreamDecoder::ReadVarintField()

NEW

+90

pw::protobuf::StreamDecoder::Advance()

NEW

+88

pw::protobuf::Decoder::ConsumeKey()

NEW

+88

pw::protobuf::StreamDecoder::BytesReader::DoSeek()

NEW

+88

pw::protobuf::StreamDecoder::CloseNestedDecoder()

NEW

+88

pw::protobuf::StreamEncoder::WriteFixed()

NEW

+80

pw::protobuf::StreamDecoder::Next()

NEW

+76

pw::protobuf::StreamEncoder::WriteVarintField()

NEW

+74

pw::protobuf::Decoder::ReadFixed()

NEW

+74

pw::protobuf::StreamDecoder::BytesReader::DoRead()

NEW

+70

pw::protobuf::FieldKey::FieldKey()

NEW

+68

pw::protobuf::StreamEncoder::WriteLengthDelimitedField()

NEW

+68

pw::protobuf::StreamEncoder::WriteVarint()

NEW

+64

pw::protobuf::StreamDecoder::CheckOkToRead()

NEW

+60

pw::protobuf::FieldKey::IsValidKey()

NEW

+60

pw::protobuf::StreamDecoder::~StreamDecoder()

NEW

+58

pw::protobuf::Decoder::ReadVarint()

NEW

+54

pw::protobuf::Decoder::SkipField()

NEW

+54

pw::protobuf::StreamEncoder::WriteFloat()

NEW

+52

pw::protobuf::Decoder::ReadUint32()

NEW

+50

pw::protobuf::Decoder::ReadSint32()

NEW

+50

pw::protobuf::Decoder::ReadSint64()

NEW

+48

pw::protobuf::StreamEncoder::CloseEncoder()

NEW

+48

pw::protobuf::StreamEncoder::WriteFixed32()

NEW

+46

pw::protobuf::Decoder::Next()

NEW

+46

pw::protobuf::WriteVarint()

NEW

+44

pw::protobuf::StreamDecoder::BytesReader::~BytesReader()

NEW

+44

pw::protobuf::StreamDecoder::CloseBytesReader()

NEW

+44

pw::protobuf::WriteLengthDelimitedKeyAndLengthPrefix()

NEW

+40

pw::protobuf::Decoder::ReadBool()

NEW

+40

pw::protobuf::StreamEncoder::WriteFixed64()

NEW

+38

pw::protobuf::StreamDecoder::GetLengthDelimitedPayloadBounds()

NEW

+36

pw::protobuf::Decoder::FieldNumber()

NEW

+36

pw::protobuf::StreamDecoder::BytesReader

NEW

+32

pw::protobuf::Decoder::ReadString()

NEW

+32

pw::protobuf::ValidFieldNumber()

NEW

+28

pw::protobuf::TagSizeBytes<>()

+9,112

Note

There’s some overhead involved in ensuring all of the encoder/decoder functionality is pulled in. Check the per-symbol breakdown for more details.

Encoder/decoder codegen overhead#

The different proto serialization/deserialization codegen methods have different overhead. Some have a higher up-front cost, but lower complexity (and therefore smaller compiler generated code) at the sites of usage. Others trade lower up-front code size cost for more complexity at the proto construction and read sites.

This example uses the following proto message to construct a variety of use cases to illustrate how code and memory requirements can change depending on the complexity of the proto message being encoded/decoded.

syntax = "proto3";

package pw.protobuf_size_report;

message ItemInfo {
  enum Access {
    NONE = 0;
    READ = 1;
    WRITE = 2;
    READ_AND_WRITE = 3;
  }
  uint64 offset = 1;
  uint32 size = 2;
  Access access_level = 3;
}

message ResponseInfo {
  oneof key {
    string key_string = 1;
    fixed32 key_token = 2;
  }

  optional int64 timestamp = 3;
  optional bool has_value = 4;
  ItemInfo item_info = 5;
}

message Response {
  repeated ResponseInfo responses = 1;
}

message LookupRequest {
  message AuthInfo {
    optional uint32 id = 1;
    optional uint32 token = 2;
  }
  oneof key {
    string key_string = 1;
    fixed32 key_token = 2;
  }
  optional uint32 items_per_response = 3;
  AuthInfo auth_info = 4;
  bool add_timestamp = 5;
}

This proto is configured with the following options file:


pw.protobuf_size_report.Reponse.responses max_count:4

Trivial proto#

This is a size report for encoding/decoding the pw.protobuf.test.ItemInfo message. This is a pretty trivial message with just a few integers.

Label

Segment

Delta

Direct wire-format proto encoder

FLASH

-2

pw::protobuf_size_report::(anonymous namespace)::GetBoolVector()

NEW

+88

pw::protobuf_size_report::(anonymous namespace)::BasicDecode()

NEW

+84

pw::protobuf_size_report::(anonymous namespace)::BasicEncode()

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::ConsumeValue<>()

+198

RAM

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::generic_encoder

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::decode_buffer

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::encode_buffer

NEW

+12

pw::protobuf_size_report::(anonymous namespace)::generic_decoder

+104

Generated wrapped wire-format encoder

FLASH

-2

pw::protobuf_size_report::(anonymous namespace)::GetBoolVector()

NEW

+172

pw::protobuf_size_report::(anonymous namespace)::BasicDecode()

NEW

+84

pw::protobuf_size_report::(anonymous namespace)::BasicEncode()

NEW

+16

pw::protobuf_size_report::pwpb::ItemInfo::MemoryEncoder::~MemoryEncoder()

NEW

+12

pw::protobuf_size_report::pwpb::ItemInfo::StreamDecoder::~StreamDecoder()

NEW

+10

pw::protobuf_size_report::(anonymous namespace)::ConsumeValue<>()

+292

RAM

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::decoder

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::encoder

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::decode_buffer

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::encode_buffer

NEW

+20

pw::protobuf_size_report::(anonymous namespace)::reader

+148

Generated message encoder

FLASH

-2

pw::protobuf_size_report::(anonymous namespace)::GetBoolVector()

NEW

+84

pw::protobuf_size_report::(anonymous namespace)::BasicEncode()

NEW

+64

pw::protobuf_size_report::(anonymous namespace)::BasicDecode()

NEW

+48

pw::protobuf_size_report::pwpb::ItemInfo::_kMessageFields

NEW

+12

pw::protobuf_size_report::pwpb::ItemInfo::MemoryEncoder::~MemoryEncoder()

NEW

+12

pw::protobuf_size_report::pwpb::ItemInfo::StreamDecoder::~StreamDecoder()

NEW

+10

pw::protobuf_size_report::(anonymous namespace)::ConsumeValue<>()

NEW

+8

pw::protobuf_size_report::pwpb::ItemInfo::kMessageFields

+236

RAM

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::decoder

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::encoder

NEW

+32

pw::protobuf_size_report::(anonymous namespace)::encode_buffer

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::decode_buffer

NEW

+20

pw::protobuf_size_report::(anonymous namespace)::reader

NEW

+16

pw::protobuf_size_report::(anonymous namespace)::message

+168

Optional and oneof#

This is a size report for encoding/decoding the pw.protobuf.test.ResponseInfo message. This is slightly more complex message that has a few explicitly optional fields, a oneof, and a submessage.

Label

Segment

Delta

Direct wire-format proto encoder

FLASH

-2

pw::protobuf_size_report::(anonymous namespace)::GetBoolVector()

NEW

+240

pw::protobuf_size_report::(anonymous namespace)::BasicEncode()

NEW

+236

pw::protobuf_size_report::(anonymous namespace)::BasicDecode()

NEW

+100

pw::protobuf_size_report::(anonymous namespace)::DecodeItemInfo()

NEW

+68

pw::protobuf_size_report::(anonymous namespace)::ConsumeValue<>()

+642

RAM

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::encoder

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::decode_buffer

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::encode_buffer

NEW

+12

pw::protobuf_size_report::(anonymous namespace)::decoder

+104

Generated wrapped wire-format encoder

FLASH

NEW

+444

pw::protobuf_size_report::(anonymous namespace)::BasicDecode()

NEW

+332

pw::protobuf_size_report::(anonymous namespace)::BasicEncode()

NEW

+218

pw::protobuf_size_report::(anonymous namespace)::DecodeItemInfo()

NEW

+84

pw::protobuf_size_report::pwpb::ResponseInfo::StreamDecoder::ReadHasValue()

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::ConsumeValue<>()

NEW

+12

pw::protobuf_size_report::pwpb::ResponseInfo::MemoryEncoder::~MemoryEncoder()

NEW

+12

pw::protobuf_size_report::pwpb::ResponseInfo::StreamDecoder::~StreamDecoder()

+1,138

RAM

NEW

+58

pw::protobuf_size_report::(anonymous namespace)::decode_buffer

NEW

+58

pw::protobuf_size_report::(anonymous namespace)::encode_buffer

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::decoder

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::encoder

NEW

+20

pw::protobuf_size_report::(anonymous namespace)::reader

+208

Generated message encoder

FLASH

-2

pw::protobuf_size_report::(anonymous namespace)::GetBoolVector()

NEW

+232

pw::protobuf_size_report::(anonymous namespace)::BasicEncode()

NEW

+108

pw::protobuf_size_report::(anonymous namespace)::BasicDecode()

NEW

+80

pw::protobuf_size_report::pwpb::ResponseInfo::_kMessageFields

NEW

+48

pw::protobuf_size_report::pwpb::ItemInfo::_kMessageFields

NEW

+28

pw::protobuf_size_report::(anonymous namespace)::ConsumeValue<>()

NEW

+14

pw::protobuf_size_report::pwpb::ResponseInfo::Message::~Message()

NEW

+12

pw::protobuf_size_report::pwpb::ResponseInfo::MemoryEncoder::~MemoryEncoder()

NEW

+12

pw::protobuf_size_report::pwpb::ResponseInfo::StreamDecoder::~StreamDecoder()

NEW

+8

pw::protobuf_size_report::pwpb::ItemInfo::kMessageFields

NEW

+8

pw::protobuf_size_report::pwpb::ResponseInfo::kMessageFields

+548

RAM

NEW

+58

pw::protobuf_size_report::(anonymous namespace)::decode_buffer

NEW

+58

pw::protobuf_size_report::(anonymous namespace)::encode_buffer

NEW

+56

pw::protobuf_size_report::(anonymous namespace)::message

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::decoder

NEW

+36

pw::protobuf_size_report::(anonymous namespace)::encoder

NEW

+20

pw::protobuf_size_report::(anonymous namespace)::reader

+264