Add a new (speed_optimized) message option that emits
__attribute__((optimize("O2"))) on the generated encode() and
calculate_size() methods. Under -Os, GCC does not inline the small
ProtoEncode helpers (write_raw_byte, encode_varint, etc.) into the
generated methods, causing significant overhead on hot paths.
Apply to SensorStateResponse and BluetoothLERawAdvertisementsResponse
which are the highest-frequency encode paths.
Add a new (speed_optimized) message option that emits
__attribute__((optimize("O2"))) on the generated encode() and
calculate_size() methods. Under -Os, GCC does not inline the small
ProtoEncode helpers (write_raw_byte, encode_varint, etc.) into the
generated methods, causing significant overhead on hot paths.
Apply to SensorStateResponse and BluetoothLERawAdvertisementsResponse
which are the highest-frequency encode paths.
CodSpeed benchmarks were building with -O2, while all firmware
targets (ESP8266, ESP32, LibreTiny) use -Os. This mismatch means
the benchmarks cannot detect inlining regressions that affect real
devices — GCC under -O2 inlines functions that -Os outlines due to
its size-conscious cost model.
Switch to -Os with -ffunction-sections/-fdata-sections for proper
dead-code stripping (needed because -Os preserves references that
-O2 optimizes away at compile time).
CodSpeed benchmarks were building with -O2, while all firmware
targets (ESP8266, ESP32, LibreTiny) use -Os. This mismatch means
the benchmarks cannot detect inlining regressions that affect real
devices — GCC under -O2 inlines functions that -Os outlines due to
its size-conscious cost model.
Remove the -Os unflag and -O2 override so benchmarks use the
platform default -Os, matching what actually runs on devices.
Neither PlatformIO nor ESP-IDF/CMake copy .inc files to the build
directory. Rename to .h so it's recognized by both build systems.
Exempt from pragma-once lint since this file is intentionally included
multiple times with different macro definitions.
Add a new message-level option (inline_encode) that causes the code
generator to inline sub-message encoding directly into the parent's
encode/calculate_size methods instead of going through the
encode_sub_message function pointer indirection.
When set on a sub-message type, the generator:
- Inlines field encoding directly (no function pointer, no backpatch overhead)
- Inlines size calculation (no separate method call)
- Skips generating standalone encode/calculate_size methods
- Validates at generation time that max encoded size < 128 bytes
Applied to BluetoothLERawAdvertisement which is encoded 12 times per
BLE advertisement batch in a hot loop.
Add a max_data_length field option to api_options.proto for string/bytes
fields. When max_data_length < 128 and force = true, the code generator
uses encode_short_string_force() — a single call that writes the tag
byte, 1-byte length varint, and raw string data with no branching. Size
calculation simplifies from calc_length(1, size) to 2 + size.
Annotate entity fields across all 25 ListEntities*Response messages:
- name and object_id: max_data_length = 120, force = true (50 fields)
- icon: max_data_length = 63 (25 fields)
The 120 and 63 values match NAME_MAX_LENGTH and ICON_MAX_LENGTH in
esphome/core/config.py, validated at config time.
Scan all enum definitions in api.proto at codegen time and automatically
populate max_value for enum-typed fields. This eliminates the need for
manual (max_value) annotations on every enum field.
When max_value < 128, the generated calculate_size uses constant-size
arithmetic instead of a function call:
- `calc_uint32(1, static_cast<uint32_t>(field))` → `field ? 2 : 0`
For repeated enum fields with constant element size, the per-element
loop is replaced with a multiply: `size += count * bytes_per_element`.
- Convert ProtoEncode::write_short_string to static method with pos param
- Fix codegen to emit ProtoEncode::write_short_string(pos, ...)
- Add PROTO_ENCODE_DEBUG_INIT to encode_fn call in encode_to_buffer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix double static_cast in enum encode precomputed tag path by
passing raw field ref instead of pre-cast value_expr.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace two separate write_raw_byte calls with a single
encode_small_varint(tag, value) call that writes both bytes
with one bounds check. Used for enum fields with max < 128.
When an enum field has max_value < 128 and a single-byte tag, emit
inline write_raw_byte calls instead of calling encode_uint32, which
avoids encode_field_raw and encode_varint_raw function call overhead.