From f2ac6b0af61714feb084e9353a07d63d9ea5c165 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 8 Jul 2025 09:25:00 -0600 Subject: [PATCH] cleanup --- esphome/components/runtime_stats/__init__.py | 10 ++++++++- .../runtime_stats/runtime_stats.cpp | 21 +++++++++++++------ .../components/runtime_stats/runtime_stats.h | 14 ++++++++----- esphome/core/application.cpp | 4 +++- esphome/core/application.h | 8 ------- esphome/core/component.cpp | 4 +++- 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/esphome/components/runtime_stats/__init__.py b/esphome/components/runtime_stats/__init__.py index 1843bdd94f..64382194ec 100644 --- a/esphome/components/runtime_stats/__init__.py +++ b/esphome/components/runtime_stats/__init__.py @@ -4,13 +4,18 @@ Runtime statistics component for ESPHome. import esphome.codegen as cg import esphome.config_validation as cv +from esphome.const import CONF_ID DEPENDENCIES = [] CONF_LOG_INTERVAL = "log_interval" +runtime_stats_ns = cg.esphome_ns.namespace("runtime_stats") +RuntimeStatsCollector = runtime_stats_ns.class_("RuntimeStatsCollector") + CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(): cv.declare_id(RuntimeStatsCollector), cv.Optional( CONF_LOG_INTERVAL, default=60000 ): cv.positive_time_period_milliseconds, @@ -32,4 +37,7 @@ async def to_code(config): # Define USE_RUNTIME_STATS when this component is used cg.add_define("USE_RUNTIME_STATS") - cg.add(cg.App.set_runtime_stats_log_interval(config[CONF_LOG_INTERVAL])) + # Create the runtime stats instance (constructor sets global_runtime_stats) + var = cg.new_Pvariable(config[CONF_ID]) + + cg.add(var.set_log_interval(config[CONF_LOG_INTERVAL])) diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index c2b43ed4ce..72411ffd6f 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -7,7 +7,11 @@ namespace esphome { -RuntimeStatsCollector runtime_stats; +namespace runtime_stats { + +RuntimeStatsCollector::RuntimeStatsCollector() : log_interval_(60000), next_log_time_(0) { + global_runtime_stats = this; +} void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_ms, uint32_t current_time) { if (component == nullptr) @@ -35,8 +39,8 @@ void RuntimeStatsCollector::record_component_time(Component *component, uint32_t } void RuntimeStatsCollector::log_stats_() { - ESP_LOGI(RUNTIME_TAG, "Component Runtime Statistics"); - ESP_LOGI(RUNTIME_TAG, "Period stats (last %" PRIu32 "ms):", this->log_interval_); + ESP_LOGI(TAG, "Component Runtime Statistics"); + ESP_LOGI(TAG, "Period stats (last %" PRIu32 "ms):", this->log_interval_); // First collect stats we want to display std::vector stats_to_display; @@ -57,13 +61,13 @@ void RuntimeStatsCollector::log_stats_() { const std::string &source = it.name; const ComponentRuntimeStats *stats = it.stats; - ESP_LOGI(RUNTIME_TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", source.c_str(), + ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", source.c_str(), stats->get_period_count(), stats->get_period_avg_time_ms(), stats->get_period_max_time_ms(), stats->get_period_time_ms()); } // Log total stats since boot - ESP_LOGI(RUNTIME_TAG, "Total stats (since boot):"); + ESP_LOGI(TAG, "Total stats (since boot):"); // Re-sort by total runtime for all-time stats std::sort(stats_to_display.begin(), stats_to_display.end(), @@ -75,7 +79,7 @@ void RuntimeStatsCollector::log_stats_() { const std::string &source = it.name; const ComponentRuntimeStats *stats = it.stats; - ESP_LOGI(RUNTIME_TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", source.c_str(), + ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", source.c_str(), stats->get_total_count(), stats->get_total_avg_time_ms(), stats->get_total_max_time_ms(), stats->get_total_time_ms()); } @@ -92,6 +96,11 @@ void RuntimeStatsCollector::process_pending_stats(uint32_t current_time) { } } +} // namespace runtime_stats + +runtime_stats::RuntimeStatsCollector *global_runtime_stats = + nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + } // namespace esphome #endif // USE_RUNTIME_STATS diff --git a/esphome/components/runtime_stats/runtime_stats.h b/esphome/components/runtime_stats/runtime_stats.h index ba4f352568..24dae46b2e 100644 --- a/esphome/components/runtime_stats/runtime_stats.h +++ b/esphome/components/runtime_stats/runtime_stats.h @@ -12,10 +12,12 @@ namespace esphome { -static const char *const RUNTIME_TAG = "runtime"; - class Component; // Forward declaration +namespace runtime_stats { + +static const char *const TAG = "runtime_stats"; + class ComponentRuntimeStats { public: ComponentRuntimeStats() @@ -87,7 +89,7 @@ struct ComponentStatPair { class RuntimeStatsCollector { public: - RuntimeStatsCollector() : log_interval_(60000), next_log_time_(0) {} + RuntimeStatsCollector(); void set_log_interval(uint32_t log_interval) { this->log_interval_ = log_interval; } uint32_t get_log_interval() const { return this->log_interval_; } @@ -113,8 +115,10 @@ class RuntimeStatsCollector { uint32_t next_log_time_; }; -// Global instance for runtime stats collection -extern RuntimeStatsCollector runtime_stats; +} // namespace runtime_stats + +extern runtime_stats::RuntimeStatsCollector + *global_runtime_stats; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace esphome diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 224989c73c..6face23e3c 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -144,7 +144,9 @@ void Application::loop() { #ifdef USE_RUNTIME_STATS // Process any pending runtime stats printing after all components have run // This ensures stats printing doesn't affect component timing measurements - runtime_stats.process_pending_stats(last_op_end_time); + if (global_runtime_stats != nullptr) { + global_runtime_stats->process_pending_stats(last_op_end_time); + } #endif // Use the last component's end time instead of calling millis() again diff --git a/esphome/core/application.h b/esphome/core/application.h index 588ab1a92a..2cdcdf9e6a 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -351,14 +351,6 @@ class Application { uint32_t get_loop_interval() const { return static_cast(this->loop_interval_); } -#ifdef USE_RUNTIME_STATS - /** Set the interval at which runtime statistics are logged. - * - * @param interval The interval in milliseconds between logging of runtime statistics. - */ - void set_runtime_stats_log_interval(uint32_t interval) { runtime_stats.set_log_interval(interval); } -#endif - void schedule_dump_config() { this->dump_config_at_ = 0; } void feed_wdt(uint32_t time = 0); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index e446dd378e..8dbd054602 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -398,7 +398,9 @@ uint32_t WarnIfComponentBlockingGuard::finish() { #ifdef USE_RUNTIME_STATS // Record component runtime stats - runtime_stats.record_component_time(this->component_, blocking_time, curr_time); + if (global_runtime_stats != nullptr) { + global_runtime_stats->record_component_time(this->component_, blocking_time, curr_time); + } #endif bool should_warn; if (this->component_ != nullptr) {