diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index d2878554296..9ed141155a5 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -65,17 +65,22 @@ void RuntimeStatsCollector::log_stats_() { if (this->period_active_count_ > 0) { uint64_t active = this->period_active_time_us_; uint64_t overhead = active > period_component_sum_us ? active - period_component_sum_us : 0; + // Use double for µs→ms conversion so multi-day uptimes (where total + // microsecond counters exceed float's ~7-digit mantissa) keep resolution. ESP_LOGI(TAG, " main_loop: iters=%" PRIu64 ", active_avg=%.3fms, active_max=%.2fms, active_total=%.1fms, " "overhead_total=%.1fms", - this->period_active_count_, active / (float) this->period_active_count_ / 1000.0f, - this->period_active_max_us_ / 1000.0f, active / 1000.0f, overhead / 1000.0f); + this->period_active_count_, + static_cast(active) / static_cast(this->period_active_count_) / 1000.0, + static_cast(this->period_active_max_us_) / 1000.0, static_cast(active) / 1000.0, + static_cast(overhead) / 1000.0); uint64_t before = this->period_before_time_us_; uint64_t tail = this->period_tail_time_us_; uint64_t accounted = before + tail; uint64_t inter = overhead > accounted ? overhead - accounted : 0; - ESP_LOGI(TAG, " main_loop_overhead_section: before=%.1fms, tail=%.1fms, inter_component=%.1fms", before / 1000.0f, - tail / 1000.0f, inter / 1000.0f); + ESP_LOGI(TAG, " main_loop_overhead_section: before=%.1fms, tail=%.1fms, inter_component=%.1fms", + static_cast(before) / 1000.0, static_cast(tail) / 1000.0, + static_cast(inter) / 1000.0); } // Log total stats since boot (only for active components - idle ones haven't changed) @@ -100,14 +105,17 @@ void RuntimeStatsCollector::log_stats_() { ESP_LOGI(TAG, " main_loop: iters=%" PRIu64 ", active_avg=%.3fms, active_max=%.2fms, active_total=%.1fms, " "overhead_total=%.1fms", - this->total_active_count_, active / (float) this->total_active_count_ / 1000.0f, - this->total_active_max_us_ / 1000.0f, active / 1000.0f, overhead / 1000.0f); + this->total_active_count_, + static_cast(active) / static_cast(this->total_active_count_) / 1000.0, + static_cast(this->total_active_max_us_) / 1000.0, static_cast(active) / 1000.0, + static_cast(overhead) / 1000.0); uint64_t before = this->total_before_time_us_; uint64_t tail = this->total_tail_time_us_; uint64_t accounted = before + tail; uint64_t inter = overhead > accounted ? overhead - accounted : 0; - ESP_LOGI(TAG, " main_loop_overhead_section: before=%.1fms, tail=%.1fms, inter_component=%.1fms", before / 1000.0f, - tail / 1000.0f, inter / 1000.0f); + ESP_LOGI(TAG, " main_loop_overhead_section: before=%.1fms, tail=%.1fms, inter_component=%.1fms", + static_cast(before) / 1000.0, static_cast(tail) / 1000.0, + static_cast(inter) / 1000.0); } // Reset period stats diff --git a/esphome/core/application.h b/esphome/core/application.h index d7c3b441da2..39617442dbc 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -886,7 +886,7 @@ inline void ESPHOME_ALWAYS_INLINE Application::loop() { // slice that the scheduler spends inside its own WarnIfComponentBlockingGuard // (scheduler.cpp) — that time is already counted in per-component stats, // so charging it again to "before" would double-count. - uint64_t loop_recorded_snap = ComponentRuntimeStats::global_recorded_us_; + uint64_t loop_recorded_snap = ComponentRuntimeStats::global_recorded_us; #endif // Get the initial loop time at the start uint32_t last_op_end_time = millis(); @@ -894,7 +894,7 @@ inline void ESPHOME_ALWAYS_INLINE Application::loop() { this->before_loop_tasks_(last_op_end_time); #ifdef USE_RUNTIME_STATS uint32_t loop_before_end_us = micros(); - uint64_t loop_before_scheduled_us = ComponentRuntimeStats::global_recorded_us_ - loop_recorded_snap; + uint64_t loop_before_scheduled_us = ComponentRuntimeStats::global_recorded_us - loop_recorded_snap; #endif for (this->current_loop_index_ = 0; this->current_loop_index_ < this->looping_components_active_end_; diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 235903cf7d4..e33652482ea 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -507,7 +507,7 @@ void PollingComponent::stop_poller() { uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; } #ifdef USE_RUNTIME_STATS -uint64_t ComponentRuntimeStats::global_recorded_us_ = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +uint64_t ComponentRuntimeStats::global_recorded_us = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) #endif void __attribute__((noinline, cold)) diff --git a/esphome/core/component.h b/esphome/core/component.h index 648cbda870c..6fbb0d5c06e 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -121,7 +121,7 @@ struct ComponentRuntimeStats { // WarnIfComponentBlockingGuard (including guards constructed by the // scheduler at scheduler.cpp) so main-loop overhead accounting can // subtract scheduled-callback time from the before_loop_tasks_ wall time. - static uint64_t global_recorded_us_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static uint64_t global_recorded_us; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) void record_time(uint32_t duration_us) { this->period_count++; @@ -132,7 +132,7 @@ struct ComponentRuntimeStats { this->total_time_us += duration_us; if (duration_us > this->total_max_time_us) this->total_max_time_us = duration_us; - global_recorded_us_ += duration_us; + global_recorded_us += duration_us; } void reset_period() { this->period_count = 0;