Commit Graph

129 Commits

Author SHA1 Message Date
J. Nick Koston bd7bdc0e2d Merge remote-tracking branch 'upstream/devirtualize-decode' into integration 2026-03-22 21:39:51 -10:00
J. Nick Koston d755922aae Merge remote-tracking branch 'upstream/dev' into devirtualize-decode 2026-03-22 21:18:09 -10:00
J. Nick Koston f059a1c2ea [api] Remove USE_API guards from api_pb2_service (aligned with parent PR) 2026-03-22 21:18:04 -10:00
J. Nick Koston f4097d5a95 [api] Devirtualize API command dispatch (#15044) 2026-03-23 19:57:40 +13:00
J. Nick Koston fbe3e7d99c [api] Emit raw tag+value writes for forced fixed32 key fields (#15051) 2026-03-22 15:28:46 -10:00
J. Nick Koston 5aff931c68 Merge remote-tracking branch 'upstream-ssh/devirtualize-decode' into integration 2026-03-21 20:52:39 -10:00
J. Nick Koston a5bd718fc9 [api] Make ProtoDecodableMessage::decode() non-virtual
decode() is never called polymorphically - all call sites in
read_message_() use concrete types. The only indirect call site was
decode_to_message(), which also always knows the concrete type.

Convert decode_to_message() to a template so the concrete type is
preserved, allowing decode() to be non-virtual. The two classes that
override decode() (ExecuteServiceArgument, ExecuteServiceRequest) now
hide the base method, which works since all calls use concrete types.

This removes one vtable slot (4 bytes) from each decodable message
class vtable, saving ~148 bytes of flash.
2026-03-21 20:51:28 -10:00
J. Nick Koston 8978ea7479 Merge remote-tracking branch 'upstream/precompute-tag-forced-varint-fields' into integration 2026-03-21 11:49:43 -10:00
J. Nick Koston da926d904e [api] Precompute tag bytes for forced varint and length-delimited fields
Extend the precomputed-tag approach from fixed32 key fields to all forced
fields with single-byte tags (field IDs 1-15). The code generator now
emits write_raw_byte(tag) followed by the raw encode primitive instead
of calling the full encode_* method.

For varint types (uint32, uint64, sint32, sint64, int64, bool, enum),
this eliminates the zero-check branch and encode_field_raw indirection.
For length-delimited types (bytes, string), it additionally skips the
encode_string wrapper.

Benchmarked on real hardware with BluetoothLERawAdvertisementsResponse
(12 advertisements per message, 10000 iterations):

ESP32 (Xtensa dual-core 240MHz):
  encode: 38498 -> 30460 ns/op (-20.9%)
  calc+encode: 48479 -> 40458 ns/op (-16.6%)

ESP32-C3 (RISC-V single-core 160MHz):
  encode: 54199 -> 40342 ns/op (-25.6%)
  calc+encode: 57800 -> 51365 ns/op (-11.1%)
2026-03-21 11:48:28 -10:00
J. Nick Koston d8d5619ba7 [api] Use write_tag_and_fixed32 and extract calculate_tag helper
- Combine tag byte + fixed32 value into single write_tag_and_fixed32()
  method: pos[0] = tag, memcpy(pos+1, &value, 4), pos += 5
- Extract calculate_tag() from duplicated computation in
  calculate_field_id_size() and encode_content
2026-03-21 00:05:53 -10:00
J. Nick Koston 2a379490e8 Merge remote-tracking branch 'upstream/remove-noinline-encode-fixed32' into integration 2026-03-20 23:57:37 -10:00
J. Nick Koston 225c770b1b [api] Use write_tag_and_fixed32 and extract calculate_tag helper
- Combine tag byte + fixed32 value into single write_tag_and_fixed32()
  method: pos[0] = tag, memcpy(pos+1, &value, 4), pos += 5
- Extract calculate_tag() from duplicated computation in
  calculate_field_id_size() and encode_content
2026-03-20 23:45:23 -10:00
J. Nick Koston 21725983fd [api] Emit raw tag+value writes for force=true fixed32 fields
Instead of ALWAYS_INLINE on encode_field_raw (which bloated all
callers), have the code generator precompute the tag byte and emit
write_raw_byte(tag) + write_fixed32_raw(value) directly.

This gives the same tight codegen (single byte store + memcpy) for
key fields without inflating encode_bool/encode_uint32/etc.

+108 bytes flash vs baseline, -48 bytes vs the ALWAYS_INLINE approach.
2026-03-20 23:28:19 -10:00
J. Nick Koston 7c1b30f37f Merge remote-tracking branch 'upstream/devirtualize-api-dispatch' into integration 2026-03-20 21:31:54 -10:00
J. Nick Koston 1d191d2461 [api] Fix review comments and add USE_API guards
- Update comments to reflect that ProtoService methods moved to
  APIConnection, not APIServerConnectionBase
- Fix comment referring to read_message as "override"
- Wrap #include "api_connection.h" and read_message_ implementation
  in #ifdef USE_API guards
2026-03-20 21:29:42 -10:00
J. Nick Koston 7d8eba85c6 Merge remote-tracking branch 'upstream/devirtualize-api-dispatch' into integration 2026-03-20 21:21:56 -10:00
J. Nick Koston 20d3e7c13a [api] Remove virtual destructor and rename read_message to read_message_
The virtual destructor was unnecessary since APIConnection is only
stored as unique_ptr<APIConnection>, never via a base class pointer.
Removing it eliminates the vtable entirely.

Rename read_message to read_message_ per clang-tidy naming convention
for protected methods.
2026-03-20 21:21:09 -10:00
J. Nick Koston e1f37675da Merge remote-tracking branch 'upstream/devirtualize-api-dispatch' into integration 2026-03-20 21:15:06 -10:00
J. Nick Koston 2067053adb [api] Remove ProtoService base class
ProtoService was an abstract interface with 6 pure virtual methods,
but APIConnection was the only concrete implementation. Move all
functionality directly into APIConnection and remove the unnecessary
virtual dispatch and vtable overhead.
2026-03-20 21:14:45 -10:00
J. Nick Koston 77d2e378e2 Merge remote-tracking branch 'upstream/devirtualize-api-dispatch' into integration 2026-03-20 21:06:22 -10:00
J. Nick Koston 391ad05d45 [api] Devirtualize API command dispatch
Move read_message() from APIServerConnectionBase into APIConnection
and drop the virtual keyword from all 64 on_* handler declarations.

Since APIConnection is final and the only subclass, the virtual
dispatch was unnecessary. With read_message and the on_* handlers
in the same class, the compiler can devirtualize the calls and
inline small handlers directly into the switch cases.
2026-03-20 20:58:54 -10:00
J. Nick Koston 78b10a24b0 Move message_name() strings to flash via LOG_STR
message_name() returned bare string literals that stayed in RAM on
ESP8266. Change return type to const LogString * and wrap with LOG_STR()
so they are stored in flash. Update log_send_message_ to use
LOG_STR_ARG() accordingly.

Also fix clang-tidy: rename append_p_esp8266_ to append_p_esp8266,
add NOLINTNEXTLINE for conditionally-unused dump_field overloads.
2026-03-19 12:40:38 -10:00
J. Nick Koston 5e64e3a3d4 [api] Store dump strings in PROGMEM to save RAM on ESP8266
All string literals in api_pb2_dump.cpp (field names, message names,
enum value names) were stored in rodata which occupies RAM on ESP8266.
This meant every API protobuf change appeared as a RAM increase in CI
when using very_verbose logging.

Add append_p() to DumpBuffer for PROGMEM-safe string reading and update
the code generator to wrap all dump string literals with ESPHOME_PSTR().
On non-ESP8266 platforms, these are no-ops with zero overhead.
2026-03-19 12:24:10 -10:00
J. Nick Koston 05d285ba86 [api] Fix heap-buffer-overflow in protobuf message dump for StringRef (#14721) 2026-03-12 07:16:53 -10:00
J. Nick Koston 6e468936ec [api] Inline ProtoVarInt::parse fast path and return consumed in struct (#14638)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 09:10:55 -10:00
J. Nick Koston be6c3c52ac [api] Add force proto field option to skip zero checks on hot path (#14610)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:59:13 -10:00
J. Nick Koston 77f2c371b2 [api] Single-pass protobuf encode for BLE proxy advertisements (#14575) 2026-03-07 07:26:34 -10:00
J. Nick Koston 42dbb51022 [api] Devirtualize protobuf encode/calculate_size (#14449)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-06 19:03:54 +00:00
J. Nick Koston f68a3ed15d [api] Remove virtual destructor from ProtoMessage (#14393) 2026-03-01 18:09:00 -10:00
J. Nick Koston 8bb577de64 [api] Split ProtoVarInt::parse into 32-bit and 64-bit phases (#14039) 2026-02-25 12:23:13 -06:00
J. Nick Koston f77da803c9 [api] Write protobuf encode output to pre-sized buffer directly (#14018) 2026-02-20 21:39:18 -06:00
J. Nick Koston 6c6da8a3cd [api] Skip class generation for empty SOURCE_CLIENT protobuf messages (#13880) 2026-02-09 18:45:24 +00:00
J. Nick Koston c658d7b57f [api] Merge auth check into base read_message, eliminate APIServerConnection (#13873) 2026-02-09 12:02:02 -06:00
J. Nick Koston 3cde3daceb [api] Collapse APIServerConnection intermediary layer (#13872) 2026-02-09 08:45:33 -06:00
J. Nick Koston 140ec0639c [api] Elide empty message construction in protobuf dispatch (#13871) 2026-02-09 03:24:45 -06:00
J. Nick Koston 55ef8393af [api] Remove is_single parameter and fix batch buffer preparation (#13773)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-05 15:19:03 +01:00
dependabot[bot] 4d05cd3059 Bump ruff from 0.14.14 to 0.15.0 (#13752)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-02-04 09:24:05 +00:00
J. Nick Koston 8d0ce49eb4 [api] Eliminate intermediate buffers in protobuf dump helpers (#13742)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 16:34:15 +01:00
J. Nick Koston 7fed9144a6 [api] Use stack buffer for VERY_VERBOSE proto message dumps (#13176) 2026-01-13 08:04:48 -10:00
J. Nick Koston 7ea6bcef88 [api] Use stack buffer for bytes field dumping in proto message logs (#13162) 2026-01-12 07:37:58 -10:00
J. Nick Koston 912f94d1e8 [api] Use StringRef for HomeassistantServiceMap.value to eliminate heap allocations (#13154)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-11 17:54:06 -10:00
Keith Burzinski f2eb61a767 [api] Proto code generator changes for #12985 (#13100)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-01-10 15:43:27 -10:00
J. Nick Koston 546cdbde0d [api] Simplify string handling by removing bifurcated client/server storage (#12822) 2026-01-07 08:23:28 -10:00
J. Nick Koston 2a5be725c8 [api] Enable zero-copy bytes SOURCE_BOTH messages (#12816) 2026-01-02 19:50:30 -10:00
J. Nick Koston e7001c5eea [api] Auto-generate zero-copy pointer access for incoming API bytes fields (#12654) 2026-01-02 14:05:37 -10:00
J. Nick Koston 6d4f4d8d23 [api] Auto-generate StringRef for incoming API string fields (#12648) 2026-01-02 08:17:05 -10:00
J. Nick Koston b47b7d43fd [api] Remove unused force parameter from encode_message (#12551) 2025-12-18 09:06:16 -07:00
J. Nick Koston fb82362e9c [api] Eliminate rx_buf heap churn and release buffers after initial sync (#12133) 2025-11-28 12:13:29 -06:00
Jonathan Swoboda 61cef0a75c [api] Fix format warnings in dump (#11999) 2025-11-19 12:58:47 -05:00
J. Nick Koston 42833c85f5 [climate] Replace std::vector<std::string> with const char* for custom fan modes and presets (#11621) 2025-11-02 23:16:39 -06:00