From e89836d0d4e45564ab983d361444b5d513613cff Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 21 Apr 2026 12:10:52 +0200 Subject: [PATCH] [api] Trim overlong/stale comments from PR --- esphome/components/api/__init__.py | 17 +++++++---------- esphome/components/api/api_server.cpp | 7 ++----- esphome/components/api/api_server.h | 14 ++------------ 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 86a87722f8..88f01620c5 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -290,13 +290,13 @@ CONFIG_SCHEMA = cv.All( ): cv.int_range(min=1, max=10), cv.SplitDefault( CONF_MAX_CONNECTIONS, - esp8266=4, # ~40KB free RAM, each connection uses ~500-1000 bytes - esp32=5, # 520KB RAM — 5 slots makes the static-RAM trade true net-negative at 1 client - rp2040=4, # 264KB RAM but LWIP constraints - bk72xx=5, # Moderate RAM — net-negative at 1 client - rtl87xx=5, # Moderate RAM — net-negative at 1 client - host=8, # Abundant resources, no BSS-slot concern - ln882x=5, # Moderate RAM — net-negative at 1 client + esp8266=4, + esp32=5, + rp2040=4, + bk72xx=5, + rtl87xx=5, + host=8, + ln882x=5, ): cv.int_range(min=1, max=20), # Maximum queued send buffers per connection before dropping connection # Each buffer uses ~8-12 bytes overhead plus actual message size @@ -336,9 +336,6 @@ async def to_code(config: ConfigType) -> None: cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY])) if CONF_LISTEN_BACKLOG in config: cg.add(var.set_listen_backlog(config[CONF_LISTEN_BACKLOG])) - # MAX_API_CONNECTIONS sizes the compile-time std::array in APIServer. - # Making this a compile-time constant (rather than a runtime set_max_connections setter) - # eliminates the std::vector heap allocation and its reallocation machinery. cg.add_define("MAX_API_CONNECTIONS", config[CONF_MAX_CONNECTIONS]) cg.add_define("API_MAX_SEND_QUEUE", config[CONF_MAX_SEND_QUEUE]) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 1120d4c529..4559168ece 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -179,9 +179,8 @@ void APIServer::remove_client_(uint8_t client_index) { // Close socket now (was deferred from on_fatal_error to allow getpeername) client->helper_->close(); - // Swap with the last populated slot and shrink the active range by one. Resetting the - // now-unused trailing slot preserves the invariant that slots [api_connection_count_, N) - // are always nullptr, which makes debugging and defensive iteration safer. + // Swap-and-reset: move the removed client to the trailing slot and null it out so slots + // [api_connection_count_, N) remain nullptr. const uint8_t last_index = this->api_connection_count_ - 1; if (client_index < last_index) { std::swap(this->clients_[client_index], this->clients_[last_index]); @@ -597,8 +596,6 @@ void APIServer::request_time() { #endif bool APIServer::is_connected_with_state_subscription() const { - // Indexed iteration (not active_clients()) because this method is const; keeps the view - // struct single-flavor in the header. for (uint8_t i = 0; i < this->api_connection_count_; i++) { if (this->clients_[i]->flags_.state_subscription) { return true; diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index b411ed770d..19fcbc531c 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -65,8 +65,6 @@ class APIServer final : public Component, void set_batch_delay(uint16_t batch_delay); uint16_t get_batch_delay() const { return batch_delay_; } void set_listen_backlog(uint8_t listen_backlog) { this->listen_backlog_ = listen_backlog; } - // Max connections is a compile-time constant (MAX_API_CONNECTIONS) set from YAML via codegen; - // the array sizing and the accept-time cap both derive from it. // Get reference to shared buffer for API connections APIBuffer &get_shared_buffer_ref() { return shared_write_buffer_; } @@ -192,9 +190,7 @@ class APIServer final : public Component, bool is_connected() const { return this->api_connection_count_ != 0; } bool is_connected_with_state_subscription() const; - // View over the active (populated) slice of clients_. Use this for range-for iteration so we - // don't walk past api_connection_count_ into unused slots. Pointer range keeps iterator - // semantics equivalent to std::vector>::iterator. + // Range-for view over the populated slice [0, api_connection_count_). using APIConnectionPtr = std::unique_ptr; class ActiveClientsView { APIConnectionPtr *begin_; @@ -293,10 +289,7 @@ class APIServer final : public Component, uint32_t reboot_timeout_{300000}; uint32_t last_connected_{0}; - // Compile-time sized array of active API connections. - // Slots [0, api_connection_count_) are populated; slots [api_connection_count_, N) are kept as - // nullptr so the invariant "touching any live slot is safe" holds. No heap allocation, no - // std::vector reallocation machinery — eliminates a persistent heap-fragmentation source. + // Slots [0, api_connection_count_) are populated; trailing slots are always nullptr. std::array, MAX_API_CONNECTIONS> clients_{}; // Vectors and strings (12 bytes each on 32-bit) // Shared proto write buffer for all connections. @@ -336,9 +329,6 @@ class APIServer final : public Component, // from cv.SplitDefault in __init__.py which sets platform-specific defaults. uint8_t listen_backlog_{4}; bool shutting_down_ = false; - // Active-slot count for clients_ (populated slots are [0, api_connection_count_)). - // Placed here to fill what used to be the 1-byte padding slot — zero size overhead versus the - // previous layout where this was the removed max_connections_ field. uint8_t api_connection_count_{0}; // 7 bytes used, 1 byte padding