Commit Graph

488 Commits

Author SHA1 Message Date
J. Nick Koston ef41caa347 Merge branch 'api-proto-max-length' into integration 2026-04-03 14:16:20 -10:00
J. Nick Koston 80502e8c39 [api] Rename encode_short_string to write_short_string 2026-04-03 14:15:19 -10:00
J. Nick Koston fd68e9a827 [api] Rename encode_raw_short_string to encode_short_string 2026-04-03 14:01:14 -10:00
J. Nick Koston 2d13def0ee [api] Add encode_raw_short_string for forced string fields with max_data_length
Replace 3-call sequence (write_raw_byte + write_raw_byte + encode_raw)
with single inlined encode_raw_short_string call for forced string
fields with max_data_length < 128. The compiler can hoist the pos
pointer across all three writes in one function boundary.
2026-04-03 14:00:01 -10:00
J. Nick Koston 675400cc31 [api] Use .empty() for string zero check in single-byte varint size 2026-04-03 13:51:25 -10:00
J. Nick Koston e174e579ed [api] Add max_data_length proto option and optimize entity name/object_id
Add max_data_length field option for string/bytes fields. When
max_data_length < 128, the codegen emits constant-size length varint
calculations and direct byte writes.

Annotate all entity name and object_id fields with
(max_data_length) = 120 and (force) = true across all 25
ListEntities*Response messages (50 fields).

Generated code changes:
- calculate_size: `calc_length(1, size)` -> `2 + size` (constant)
- encode: `encode_string(N, ref)` -> `write_raw_byte(tag) + write_raw_byte(len) + encode_raw(data, len)`

Eliminates 2 function calls per field per entity list response,
removes zero-check branches, and removes varint size computation.
2026-04-03 13:33:51 -10:00
J. Nick Koston 85d9f36028 Merge remote-tracking branch 'upstream/api-proto-max-value-codegen' into integration 2026-04-03 12:48:23 -10:00
J. Nick Koston 9ece286a26 [api] Simplify _get_single_byte_varint_size 2026-04-03 12:32:32 -10:00
J. Nick Koston fa80caf0ff [api] Fall back to RAW_ENCODE_MAP when SMALL_MAP has no entry 2026-04-03 12:31:44 -10:00
J. Nick Koston f3238a857e [api] Select encode map before lookup 2026-04-03 12:31:01 -10:00
J. Nick Koston 02b424388e [api] Use RAW_ENCODE_SMALL_MAP for max_value encode optimization
Replace inline encode_func check with a lookup table, matching the
existing RAW_ENCODE_MAP pattern.
2026-04-03 12:28:51 -10:00
J. Nick Koston 363d811cc1 [api] Use _get_simple_size_calculation for FixedArrayBytesType fallback
Replace inline calc_length/calc_length_force formatting with the
existing helper method.
2026-04-03 12:27:55 -10:00
J. Nick Koston 1e68a90ac9 [api] Extract _get_single_byte_varint_size helper in codegen
Refactor the constant-size varint pattern into a reusable helper
method on the TypeInfo base class, used by both UInt32Type (max_value)
and FixedArrayBytesType (fixed_array_size < 128).
2026-04-03 12:26:51 -10:00
J. Nick Koston e35aa729f3 [api] Add max_value proto option for constant-size varint codegen
Add a max_value field option to api_options.proto that tells the code
generator the maximum value a field can have. When max_value < 128,
the generated calculate_size() uses constant arithmetic instead of
calling varint size functions, and encode() uses direct byte writes
instead of varint encoding.

Also optimize FixedArrayBytesType: when fixed_array_size < 128, the
length varint is always 1 byte, so calculate_size() uses constant
arithmetic and encode() uses write_raw_byte for the length.

Applied to BluetoothLERawAdvertisement.address_type (max_value=4).

Measured on ESP32 (upstairsdesk89proxy):
- BluetoothLERawAdvertisement::calculate_size: 88 → 71 bytes (-19%)
- BluetoothLERawAdvertisement::encode: 199 → 179 bytes (-10%)
- Total BLE proxy hot path: 1807 → 1770 bytes (-37 bytes)
2026-04-03 12:21:37 -10:00
J. Nick Koston 4d4ff0303d Merge remote-tracking branch 'upstream/dev' into integration 2026-04-03 10:03:23 -10:00
Clyde Stubbs 6f05e3d204 [ci] Run ci-custom.py as a pre-commit check (#15411) 2026-04-03 12:54:44 +11:00
J. Nick Koston 6bad85d3e2 Merge remote-tracking branch 'origin/fix-preferences-log-spam' into integration 2026-03-30 22:39:11 -10:00
Guillermo Ruffino ef65e47bc5 [schema] generator fixes (#15276) 2026-03-31 13:08:50 +13:00
J. Nick Koston 8a802ca666 [benchmark] Add BLE raw advertisement proto encode benchmarks (#15289) 2026-03-29 11:54:07 -10:00
J. Nick Koston 3e89858e39 Merge remote-tracking branch 'origin/api-sint32-short-varint' into integration 2026-03-28 21:43:28 -10:00
J. Nick Koston 52897fd067 [api] Add 2-byte inline fast path for sint32 varint encode/size
Add encode_varint_raw_short() and ProtoSize::varint_short() that
inline both the 1-byte and 2-byte varint paths, falling back to
the noinline slow path for 3+ bytes.

Use these for sint32 fields (zigzag encoding), where values like
RSSI (-100 to 0) produce zigzag values that are 1-2 bytes. This
avoids a function call for the common case without bloating the
generic encode_varint_raw fast path.
2026-03-28 17:27:40 -10:00
J. Nick Koston 777e162070 [benchmark] Add BLE raw advertisement proto encode benchmarks
Add CodSpeed benchmarks for BluetoothLERawAdvertisementsResponse
(12 advertisements) covering calculate_size, encode, calc+encode,
and fresh-buffer paths.

Includes a lightweight bluetooth_proxy stub header in
tests/benchmarks/stubs/ so the api component can compile with
USE_BLUETOOTH_PROXY on the host platform without pulling in
ESP32 BLE dependencies.
2026-03-28 17:08:52 -10:00
J. Nick Koston db15bb2494 Merge remote-tracking branch 'upstream/callback-manager-no-vector' into integration 2026-03-28 08:27:47 -10:00
Jonathan Swoboda b6abfec82e [core] Fix area/device hash collision validation not running (#15259) 2026-03-27 22:22:24 -04:00
J. Nick Koston 968fa1cadd Merge remote-tracking branch 'origin/api-warning-message' into integration 2026-03-24 10:19:55 -10:00
Jonathan Swoboda 3cd50f0495 [ci] Block new CONF_ constants from being added to esphome/const.py (#15145) 2026-03-24 09:31:08 -10:00
J. Nick Koston 793813790a [api] Precompute tag bytes for forced varint and length-delimited fields (#15067) 2026-03-24 01:52:39 +00:00
J. Nick Koston 382de7ca90 [api] Store dump strings in PROGMEM to save RAM on ESP8266 (#14982) 2026-03-23 13:40:53 -10:00
J. Nick Koston 04032914e9 Merge remote-tracking branch 'upstream/dev' into integration
# Conflicts:
#	esphome/components/ethernet/__init__.py
#	esphome/components/ethernet/ethernet_component_esp32.cpp
2026-03-23 12:45:25 -10:00
J. Nick Koston 9e645c72aa Merge branch 'api/peel-first-write-iteration' into integration 2026-03-23 12:01:59 -10:00
Daniel Kent 4c1363b104 [spi] Add LOG_SPI_DEVICE macro (#15118) 2026-03-23 15:07:40 -04:00
J. Nick Koston 4b0c711f77 [ci] Ban std::bind in new C++ code (#14969) 2026-03-23 08:23:35 -10:00
J. Nick Koston 36d2e58b11 [api] Make ProtoDecodableMessage::decode() non-virtual (#15076) 2026-03-23 08:23:08 -10:00
Kevin Ahrendt 5a984b54cf [audio] Bump microOpus to avoid creating an extra opus-staged directory (#14974) 2026-03-23 08:31:05 -04:00
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