[core] Inline api_is_connected() for hot-path callers

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.
This commit is contained in:
J. Nick Koston
2026-04-21 11:14:12 +02:00
parent a8bd035b62
commit b8de93aabe
2 changed files with 20 additions and 15 deletions
-13
View File
@@ -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) {
+20 -2
View File
@@ -1,10 +1,28 @@
#pragma once
#include <string>
#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();