Optimize OTA loop to avoid unnecessary stack allocations (#9129)

This commit is contained in:
J. Nick Koston 2025-06-19 03:33:00 +02:00 committed by GitHub
parent 8ba22183b9
commit 40a5638005
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -26,19 +26,19 @@ void ESPHomeOTAComponent::setup() {
ota::register_ota_platform(this); ota::register_ota_platform(this);
#endif #endif
server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections
if (server_ == nullptr) { if (this->server_ == nullptr) {
ESP_LOGW(TAG, "Could not create socket"); ESP_LOGW(TAG, "Could not create socket");
this->mark_failed(); this->mark_failed();
return; return;
} }
int enable = 1; int enable = 1;
int err = server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); int err = this->server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if (err != 0) { if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err); ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
// we can still continue // we can still continue
} }
err = server_->setblocking(false); err = this->server_->setblocking(false);
if (err != 0) { if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err); ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
this->mark_failed(); this->mark_failed();
@ -54,14 +54,14 @@ void ESPHomeOTAComponent::setup() {
return; return;
} }
err = server_->bind((struct sockaddr *) &server, sizeof(server)); err = this->server_->bind((struct sockaddr *) &server, sizeof(server));
if (err != 0) { if (err != 0) {
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno); ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
this->mark_failed(); this->mark_failed();
return; return;
} }
err = server_->listen(4); err = this->server_->listen(4);
if (err != 0) { if (err != 0) {
ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno); ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno);
this->mark_failed(); this->mark_failed();
@ -82,7 +82,14 @@ void ESPHomeOTAComponent::dump_config() {
#endif #endif
} }
void ESPHomeOTAComponent::loop() { this->handle_(); } void ESPHomeOTAComponent::loop() {
// Skip handle_() call if no client connected and no incoming connections
// This optimization reduces idle loop overhead when OTA is not active
// Note: No need to check server_ for null as the component is marked failed in setup() if server_ creation fails
if (this->client_ != nullptr || this->server_->ready()) {
this->handle_();
}
}
static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01; static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
@ -101,23 +108,21 @@ void ESPHomeOTAComponent::handle_() {
size_t size_acknowledged = 0; size_t size_acknowledged = 0;
#endif #endif
if (client_ == nullptr) { if (this->client_ == nullptr) {
// Check if the server socket is ready before accepting // We already checked server_->ready() in loop(), so we can accept directly
if (this->server_->ready()) { struct sockaddr_storage source_addr;
struct sockaddr_storage source_addr; socklen_t addr_len = sizeof(source_addr);
socklen_t addr_len = sizeof(source_addr); this->client_ = this->server_->accept((struct sockaddr *) &source_addr, &addr_len);
client_ = server_->accept((struct sockaddr *) &source_addr, &addr_len); if (this->client_ == nullptr)
} return;
} }
if (client_ == nullptr)
return;
int enable = 1; int enable = 1;
int err = client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int)); int err = this->client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int));
if (err != 0) { if (err != 0) {
ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno); ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno);
client_->close(); this->client_->close();
client_ = nullptr; this->client_ = nullptr;
return; return;
} }