From 8b9c4d050ddb8393dd1904b04658bfe790f9c1fe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 8 Mar 2026 17:37:55 -1000 Subject: [PATCH] Reduce parse() inline size by folding len==0 into slow path Move the len==0 check from the inlined fast path into parse_slow(), saving one branch + one return-value setup per inline site (~6-8 bytes per call site on Xtensa/xtensa-lx106). Co-Authored-By: Claude Opus 4.6 --- esphome/components/api/proto.cpp | 2 ++ esphome/components/api/proto.h | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 7e011858499..4cbc8f46c2d 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -21,6 +21,8 @@ void ProtoWriteBuffer::encode_varint_raw_slow_(uint32_t value) { } ProtoVarIntResult ProtoVarInt::parse_slow(const uint8_t *buffer, uint32_t len) { + if (len == 0) + return {0, 0}; // Multi-byte varint: first byte already checked to have high bit set uint32_t result32 = buffer[0] & 0x7F; #ifdef USE_API_VARINT64 diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 04cb0cc85c0..55054ed1573 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -132,11 +132,11 @@ class ProtoVarInt { /// Parse a varint from buffer. Returns result with consumed=0 on failure. static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len) { - if (len == 0) - return {0, 0}; // Fast path: single-byte varints (0-127) are the most common case // (booleans, small enums, field tags, small message sizes/types). - if ((buffer[0] & 0x80) == 0) [[likely]] + // len==0 check is folded into the condition to minimize inline size; + // parse_slow() handles len==0. + if (len != 0 && (buffer[0] & 0x80) == 0) [[likely]] return {buffer[0], 1}; return parse_slow(buffer, len); }