Serializing nested messages repeatedly recalculates the serialized size of the same subtrees.
In EmbeddedProto 3.6.1 and develop-v4 at b5620a9b8a83a85812a483fc568292551e6e154d, Field::serialized_size() serializes the complete field into a new MessageSizeCalculator. Generated code then serializes that field again to produce the actual output.
For a chain of nested messages, the number of serialize() calls grows exponentially:
| Nesting depth |
Calls |
Output size |
| 8 |
255 |
15 bytes |
| 10 |
1,023 |
19 bytes |
| 12 |
4,095 |
23 bytes |
| 16 |
65,535 |
31 bytes |
The v4 partial-serialization path also recalculates nested sizes and does not retain the outgoing size in MessageState.
Expected behavior
Each nested message size should be calculated at most once during one immutable serialization operation. Later serialization calls must still observe message mutations.
Measured impact
On an ESP32-C6, adding a bounded per-serialization size cache reduced response serialization from approximately 13.8 ms to 0.81 ms, while producing byte-identical output.
Suggested direction
Introduce a serialization-scoped size cache or pass a size-calculation context through generated serialization code. It should:
- avoid dynamic allocation;
- remain compatible with supported C++ versions;
- handle repeated and optional messages;
- work with full and partial serialization;
- discard cached sizes after each serialization call.
Serializing nested messages repeatedly recalculates the serialized size of the same subtrees.
In EmbeddedProto 3.6.1 and
develop-v4atb5620a9b8a83a85812a483fc568292551e6e154d,Field::serialized_size()serializes the complete field into a newMessageSizeCalculator. Generated code then serializes that field again to produce the actual output.For a chain of nested messages, the number of
serialize()calls grows exponentially:The v4 partial-serialization path also recalculates nested sizes and does not retain the outgoing size in
MessageState.Expected behavior
Each nested message size should be calculated at most once during one immutable serialization operation. Later serialization calls must still observe message mutations.
Measured impact
On an ESP32-C6, adding a bounded per-serialization size cache reduced response serialization from approximately 13.8 ms to 0.81 ms, while producing byte-identical output.
Suggested direction
Introduce a serialization-scoped size cache or pass a size-calculation context through generated serialization code. It should: