From 5a8e54301f46c5ef5dd5ad25d1e8d57f57a0bc86 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 29 Mar 2026 11:10:56 -1000 Subject: [PATCH] [api] Call write_raw_slow_ directly from cold paths to save flash write_frame_ (handshake) and bad indicator response are cold paths that don't benefit from the inlined write_raw_ fast path. Calling write_raw_slow_ directly avoids expanding the inline fast path code at these call sites, saving ~70 bytes per site. --- esphome/components/api/api_frame_helper_noise.cpp | 5 +++-- esphome/components/api/api_frame_helper_plaintext.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index e78f0217439..d13a3472c4f 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -539,16 +539,17 @@ APIError APINoiseFrameHelper::write_frame_(const uint8_t *data, uint16_t len) { header[1] = (uint8_t) (len >> 8); header[2] = (uint8_t) len; + // Handshake-only path — use slow path directly to avoid inlining write_raw_ fast path struct iovec iov[2]; iov[0].iov_base = header; iov[0].iov_len = 3; if (len == 0) { - return this->write_raw_(iov, 1, 3); // Just header + return this->write_raw_slow_(iov, 1, 3, -1); } iov[1].iov_base = const_cast(data); iov[1].iov_len = len; - return this->write_raw_(iov, 2, 3 + len); // Header + data + return this->write_raw_slow_(iov, 2, 3 + len, -1); } /** Initiate the data structures for the handshake. diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index a726d2bc46b..c9e178a900b 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -219,11 +219,15 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { "Bad indicator byte"; char msg[INDICATOR_MSG_SIZE]; memcpy_P(msg, MSG_PROGMEM, INDICATOR_MSG_SIZE); - this->write_raw_(msg, INDICATOR_MSG_SIZE); + // Error path — use slow path directly to avoid inlining write_raw_ fast path + struct iovec iov = {msg, INDICATOR_MSG_SIZE}; + this->write_raw_slow_(&iov, 1, INDICATOR_MSG_SIZE, -1); #else static const char MSG[] = "\x00" "Bad indicator byte"; - this->write_raw_(MSG, INDICATOR_MSG_SIZE); + // Error path — use slow path directly to avoid inlining write_raw_ fast path + struct iovec iov = {const_cast(MSG), INDICATOR_MSG_SIZE}; + this->write_raw_slow_(&iov, 1, INDICATOR_MSG_SIZE, -1); #endif } return aerr;