[api] Inline ProtoSize::varint fast path for hot loop performance

Split ProtoSize::varint() into an always-inlined fast path (value < 128)
and a noinline slow path, eliminating indirect function calls on the BLE
advertisement encode hot path. Also force-inline calc_uint32() and
calc_length() so the compiler fully inlines size calculations per
advertisement instead of emitting out-of-line calls.

Verified via Xtensa disassembly: eliminates ~80 indirect function calls
per 16-advertisement batch flush (3 calc + varint per advertisement).
Total hot path code reduced from 24 to 21 functions.
This commit is contained in:
J. Nick Koston
2026-03-07 15:20:58 -10:00
parent 888f3d804b
commit 05896c38e8
2 changed files with 29 additions and 16 deletions
+13
View File
@@ -8,6 +8,19 @@ namespace esphome::api {
static const char *const TAG = "api.proto";
uint32_t ProtoSize::varint_slow_(uint32_t value) {
// value is guaranteed >= 128 here (fast path handled inline)
if (value < 16384) {
return 2; // 14 bits
} else if (value < 2097152) {
return 3; // 21 bits
} else if (value < 268435456) {
return 4; // 28 bits
} else {
return 5; // 32 bits (maximum for uint32_t)
}
}
#ifdef USE_API_VARINT64
optional<ProtoVarInt> ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed,
uint32_t result32) {