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);
#endif
server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections
if (server_ == nullptr) {
this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections
if (this->server_ == nullptr) {
ESP_LOGW(TAG, "Could not create socket");
this->mark_failed();
return;
}
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) {
ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
// we can still continue
}
err = server_->setblocking(false);
err = this->server_->setblocking(false);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
this->mark_failed();
@ -54,14 +54,14 @@ void ESPHomeOTAComponent::setup() {
return;
}
err = server_->bind((struct sockaddr *) &server, sizeof(server));
err = this->server_->bind((struct sockaddr *) &server, sizeof(server));
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
this->mark_failed();
return;
}
err = server_->listen(4);
err = this->server_->listen(4);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno);
this->mark_failed();
@ -82,7 +82,14 @@ void ESPHomeOTAComponent::dump_config() {
#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;
@ -101,23 +108,21 @@ void ESPHomeOTAComponent::handle_() {
size_t size_acknowledged = 0;
#endif
if (client_ == nullptr) {
// Check if the server socket is ready before accepting
if (this->server_->ready()) {
if (this->client_ == nullptr) {
// We already checked server_->ready() in loop(), so we can accept directly
struct sockaddr_storage source_addr;
socklen_t addr_len = sizeof(source_addr);
client_ = server_->accept((struct sockaddr *) &source_addr, &addr_len);
}
}
if (client_ == nullptr)
this->client_ = this->server_->accept((struct sockaddr *) &source_addr, &addr_len);
if (this->client_ == nullptr)
return;
}
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) {
ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno);
client_->close();
client_ = nullptr;
this->client_->close();
this->client_ = nullptr;
return;
}