From b8de93aabe6396bb0871be42c0c700fce879034b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 21 Apr 2026 11:14:12 +0200 Subject: [PATCH] [core] Inline api_is_connected() for hot-path callers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the api_is_connected() definition from util.cpp to util.h and mark it ESPHOME_ALWAYS_INLINE. The body is trivial — a nullptr check on global_api_server plus APIServer::is_connected() (which is !clients_.empty()) — so the out-of-line call8 was pure overhead for hot paths that check connectivity every loop tick (e.g. zwave_proxy::loop, serial_proxy::loop). With USE_API disabled the function collapses to "return false" at compile time and folds away entirely. util.h now pulls in api_server.h under USE_API. Only 25 .cpp files include util.h and all of them are on USE_API builds in practice (wifi, safe_mode, nextion, web_server, etc.), so the additional transitive include is essentially free on the platforms that matter. Measured on ESP32-S3: the call8 in ZWaveProxy::loop() is replaced by 5 inline Xtensa instructions (load global_api_server, deref, null check, clients_ start/finish compare) — no call overhead, no stack frame. --- esphome/core/util.cpp | 13 ------------- esphome/core/util.h | 22 ++++++++++++++++++++-- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/esphome/core/util.cpp b/esphome/core/util.cpp index 996cf8e310..cb6ed671de 100644 --- a/esphome/core/util.cpp +++ b/esphome/core/util.cpp @@ -4,25 +4,12 @@ #include "esphome/core/version.h" #include "esphome/core/log.h" -#ifdef USE_API -#include "esphome/components/api/api_server.h" -#endif - #ifdef USE_MQTT #include "esphome/components/mqtt/mqtt_client.h" #endif namespace esphome { -bool api_is_connected() { -#ifdef USE_API - if (api::global_api_server != nullptr) { - return api::global_api_server->is_connected(); - } -#endif - return false; -} - bool mqtt_is_connected() { #ifdef USE_MQTT if (mqtt::global_mqtt_client != nullptr) { diff --git a/esphome/core/util.h b/esphome/core/util.h index 1ca0173eab..8f90aa3411 100644 --- a/esphome/core/util.h +++ b/esphome/core/util.h @@ -1,10 +1,28 @@ #pragma once #include + +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + +#ifdef USE_API +#include "esphome/components/api/api_server.h" +#endif + namespace esphome { -/// Return whether the node has at least one client connected to the native API -bool api_is_connected(); +/// Return whether the node has at least one client connected to the native API. +/// +/// Inline so that hot-path callers (e.g. component loop() ticks that check connectivity every +/// iteration) can skip the call8/return pair. With USE_API disabled this trivially returns false +/// and collapses at compile time. +#ifdef USE_API +ESPHOME_ALWAYS_INLINE inline bool api_is_connected() { + return api::global_api_server != nullptr && api::global_api_server->is_connected(); +} +#else +ESPHOME_ALWAYS_INLINE inline bool api_is_connected() { return false; } +#endif /// Return whether the node has an active connection to an MQTT broker bool mqtt_is_connected();