From 4089a9fc9ed980e2ea488c5b59f20852b40ef6a6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 May 2025 13:19:45 -0500 Subject: [PATCH] save copy on each loop if no reads (common case) --- esphome/core/application.cpp | 18 ++++++++++++++++-- esphome/core/application.h | 5 +++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index b67a96eec7..a3bfbfe049 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -142,10 +142,18 @@ void Application::loop() { } } this->socket_fds_changed_ = false; + // When socket list changes, we need to copy the new base_read_fds_ + this->read_fds_is_cleared_ = false; } - // Copy base fd_set before each select - this->read_fds_ = this->base_read_fds_; + // Copy base fd_set only if necessary + // If read_fds_ is already cleared (all zeros), we can skip the copy + // We only need to copy if: + // 1. Socket list changed (handled above) + // 2. read_fds_ contains set bits from previous select + if (!this->read_fds_is_cleared_) { + this->read_fds_ = this->base_read_fds_; + } // Convert delay_time (milliseconds) to timeval struct timeval tv; @@ -174,11 +182,17 @@ void Application::loop() { ESP_LOGW(TAG, "select() failed with errno %d", errno); delay(delay_time); } + // Error case - assume we need to copy next time + this->read_fds_is_cleared_ = false; } else if (ret > 0) { ESP_LOGVV(TAG, "select() woke early: %d socket(s) ready (saved up to %ums)", ret, delay_time); + // Some fds were ready - read_fds_ has set bits, we'll need to copy next time + this->read_fds_is_cleared_ = false; } else { // ret == 0: timeout occurred (normal) ESP_LOGVV(TAG, "select() timeout after %ums (no sockets ready)", delay_time); + // Timeout clears all bits in read_fds_ - we can skip the copy next time + this->read_fds_is_cleared_ = true; } } else { // No sockets registered, use regular delay diff --git a/esphome/core/application.h b/esphome/core/application.h index 34fad11584..fba1b77238 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -586,8 +586,9 @@ class Application { bool socket_fds_changed_{false}; // Flag to rebuild base_read_fds_ when socket_fds_ changes int max_fd_{-1}; // Highest file descriptor number for select() #if defined(FD_SETSIZE) && !defined(USE_SOCKET_IMPL_LWIP_TCP) - fd_set base_read_fds_{}; // Cached fd_set rebuilt only when socket_fds_ changes - fd_set read_fds_{}; // Working fd_set for select(), copied from base_read_fds_ + fd_set base_read_fds_{}; // Cached fd_set rebuilt only when socket_fds_ changes + fd_set read_fds_{}; // Working fd_set for select(), copied from base_read_fds_ + bool read_fds_is_cleared_{false}; // True when read_fds_ is already cleared (all zeros) #endif };