From 123dd4f1379d1bac86e7bdc1c57f058f9a2c4e55 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 1 Apr 2026 13:40:03 -1000 Subject: [PATCH] [core] Reduce runtime_stats measurement overhead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inline record_runtime_stats_() to eliminate the non-inlined function call overhead per component per loop iteration. Extract check_blocking_() as an inline helper for readability. The millis() return value stays in the caller's clock domain — only the micros()-based stats recording is inlined alongside it. --- esphome/core/component.h | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/esphome/core/component.h b/esphome/core/component.h index 6e43e2556b..cccdad9607 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -628,22 +628,15 @@ class WarnIfComponentBlockingGuard { started_us_(micros()) #endif { -#ifdef USE_RUNTIME_STATS - // Use micros()-derived ms for both stats and blocking detection so clocks match - this->started_ = this->started_us_ / 1000U; -#endif } - // Finish the timing operation and return the current time + // Finish the timing operation and return the current time (millis) inline uint32_t HOT finish() { #ifdef USE_RUNTIME_STATS - // Single micros() call serves both runtime stats and blocking detection. - // Converting to millis avoids the separate millis() call. - uint32_t curr_time = this->record_runtime_stats_(); -#else - uint32_t curr_time = millis(); + this->record_runtime_stats_(); #endif - this->check_blocking_(curr_time); + uint32_t curr_time = millis(); + this->check_blocking_(curr_time - this->started_); return curr_time; } @@ -654,18 +647,12 @@ class WarnIfComponentBlockingGuard { Component *component_; #ifdef USE_RUNTIME_STATS uint32_t started_us_; - // Record runtime stats and return current time in ms (derived from micros()) - inline uint32_t record_runtime_stats_() { - uint32_t end_us = micros(); - this->component_->runtime_stats_.record_time(end_us - this->started_us_); - return end_us / 1000U; - } + inline void record_runtime_stats_() { this->component_->runtime_stats_.record_time(micros() - this->started_us_); } #endif // Fast path: compare against constant threshold in ms (computed at compile time from centiseconds) - inline void check_blocking_(uint32_t curr_time) { + inline void check_blocking_(uint32_t blocking_time) { #ifndef USE_BENCHMARK static constexpr uint32_t WARN_IF_BLOCKING_OVER_MS = static_cast(WARN_IF_BLOCKING_OVER_CS) * 10U; - uint32_t blocking_time = curr_time - this->started_; if (blocking_time > WARN_IF_BLOCKING_OVER_MS) [[unlikely]] { warn_blocking(this->component_, blocking_time); }