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

NEW

+822

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

NEW

+738

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

NEW

+654

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

NEW

+276

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

NEW

+232

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

NEW

+224

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

NEW

+208

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

NEW

+196

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

NEW

+176

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

NEW

+168

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

NEW

+168

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

NEW

+126

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

NEW

+120

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

NEW

+112

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

NEW

+110

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

NEW

+108

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

NEW

+104

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

NEW

+100

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

NEW

+98

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

NEW

+96

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

NEW

+90

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

NEW

+90

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

NEW

+90

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

NEW

+88

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

NEW

+84

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

NEW

+84

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

NEW

+80

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

NEW

+78

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

NEW

+74

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

NEW

+70

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

NEW

+70

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

NEW

+64

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

NEW

+64

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

NEW

+60

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

NEW

+60

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

NEW

+58

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

NEW

+54

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

NEW

+54

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

NEW

+52

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

NEW

+52

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

NEW

+50

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

NEW

+48

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

NEW

+46

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

NEW

+44

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

NEW

+44

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

NEW

+44

pw::protobuf::WriteLengthDelimitedKeyAndLengthPrefix()

NEW

+42

pw::protobuf::WriteVarint()

NEW

+40

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

NEW

+40

pw::protobuf::TagSizeBytes<>()

NEW

+38

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

NEW

+36

pw::protobuf::StreamDecoder::BytesReader

NEW

+32

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

NEW

+32

pw::protobuf::ValidFieldNumber()

NEW

+22

pw::protobuf::StreamEncoder::WriteZigzagVarint()

+6,810

Including table-based Message encoder and decoder

FLASH

NEW

+1,264

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

NEW

+1,064

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

NEW

+822

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

NEW

+738

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

NEW

+654

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

NEW

+276

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

NEW

+232

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

NEW

+224

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

NEW

+208

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

NEW

+196

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

NEW

+176

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

NEW

+168

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

NEW

+168

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

NEW

+126

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

NEW

+120

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

NEW

+120

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

NEW

+112

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

NEW

+110

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

NEW

+108

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

NEW

+104

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

NEW

+100

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

NEW

+98

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

NEW

+96

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

NEW

+90

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

NEW

+90

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

NEW

+90

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

NEW

+88

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

NEW

+84

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

NEW

+84

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

NEW

+80

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

NEW

+78

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

NEW

+74

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

NEW

+70

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

NEW

+70

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

NEW

+64

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

NEW

+64

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

NEW

+60

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

NEW

+60

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

NEW

+58

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

NEW

+54

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

NEW

+54

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

NEW

+52

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

NEW

+52

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

NEW

+50

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

NEW

+48

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

NEW

+46

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

NEW

+44

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

NEW

+44

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

NEW

+44

pw::protobuf::WriteLengthDelimitedKeyAndLengthPrefix()

NEW

+42

pw::protobuf::TagSizeBytes<>()

NEW

+42

pw::protobuf::WriteVarint()

NEW

+40

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

NEW

+38

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

NEW

+36

pw::protobuf::StreamDecoder::BytesReader

NEW

+32

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

NEW

+32

pw::protobuf::ValidFieldNumber()

NEW

+22

pw::protobuf::StreamEncoder::WriteZigzagVarint()

+9,260

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

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<>()

+200

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

NEW

+172

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

NEW

+84

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

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<>()

+290

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

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

+238

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

NEW

+236

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

NEW

+232

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<>()

+636

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

+492

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

NEW

+328

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

NEW

+214

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

NEW

+36

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

NEW

+16

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

NEW

+12

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

+1,098

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

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

+18

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

+554

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