From 599f784a9054f94c037961cdb2a231a923eb7ea7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 3 Apr 2026 22:46:36 -1000 Subject: [PATCH] fix bloat --- esphome/components/api/api_connection.cpp | 6 ++++++ esphome/components/api/api_connection.h | 11 +++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 9b8dce7b41a..2f8c6f4abd1 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1997,6 +1997,12 @@ bool APIConnection::send_message_(uint32_t payload_size, uint8_t message_type, M return this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type); } // encode_to_buffer is defined inline in api_connection.h (ESPHOME_ALWAYS_INLINE) + +// Noinline wrapper for zero-payload messages — single shared copy instead of +// duplicating encode_to_buffer at each cold call site. +uint16_t APIConnection::encode_empty_to_buffer(const void *msg, APIConnection *conn, uint32_t remaining_size) { + return encode_to_buffer(0, &encode_msg_noop, msg, conn, remaining_size); +} bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE); diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 037b13d17c1..10972e04863 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -403,9 +403,8 @@ class APIConnection final : public APIServerConnectionBase { bool send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, const void *msg); // Non-template buffer management for batch encoding. - // ALWAYS_INLINE so it merges into each call site (encode_message_to_buffer, - // fill_and_encode_entity_state) — the compiler can then inline the encode_fn - // callback and eliminate the indirect call. + // ALWAYS_INLINE so it merges into each call site — the compiler can then + // inline the encode_fn callback and eliminate the indirect call. static inline uint16_t ESPHOME_ALWAYS_INLINE encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg, APIConnection *conn, uint32_t remaining_size) { @@ -450,10 +449,14 @@ class APIConnection final : public APIServerConnectionBase { return static_cast(total_calculated_size); } + // Noinline path for zero-payload messages (ping, disconnect, list_info_done). + // Avoids duplicating encode_to_buffer at each cold call site. + static uint16_t encode_empty_to_buffer(const void *msg, APIConnection *conn, uint32_t remaining_size); + // Thin template wrapper — computes size, delegates buffer work to non-template helper template static uint16_t encode_message_to_buffer(T &msg, APIConnection *conn, uint32_t remaining_size) { if constexpr (T::ESTIMATED_SIZE == 0) { - return encode_to_buffer(0, &encode_msg_noop, &msg, conn, remaining_size); + return encode_empty_to_buffer(&msg, conn, remaining_size); } else { return encode_to_buffer(msg.calculate_size(), &proto_encode_msg, &msg, conn, remaining_size); }