ESPHome 2026.2.1
Loading...
Searching...
No Matches
runtime_stats.cpp
Go to the documentation of this file.
1#include "runtime_stats.h"
2
3#ifdef USE_RUNTIME_STATS
4
6#include <algorithm>
7
8namespace esphome {
9
10namespace runtime_stats {
11
12RuntimeStatsCollector::RuntimeStatsCollector() : log_interval_(60000), next_log_time_(0) {
14}
15
16void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_ms, uint32_t current_time) {
17 if (component == nullptr)
18 return;
19
20 // Record stats using component pointer as key
21 this->component_stats_[component].record_time(duration_ms);
22
23 if (this->next_log_time_ == 0) {
24 this->next_log_time_ = current_time + this->log_interval_;
25 return;
26 }
27}
28
30 // First pass: count active components
31 size_t count = 0;
32 for (const auto &it : this->component_stats_) {
33 if (it.second.get_period_count() > 0) {
34 count++;
35 }
36 }
37
38 ESP_LOGI(TAG,
39 "Component Runtime Statistics\n"
40 " Period stats (last %" PRIu32 "ms): %zu active components",
41 this->log_interval_, count);
42
43 if (count == 0) {
44 return;
45 }
46
47 // Stack buffer sized to actual active count (up to 256 components), heap fallback for larger
49 Component **sorted = buffer.get();
50
51 // Second pass: fill buffer with active components
52 size_t idx = 0;
53 for (const auto &it : this->component_stats_) {
54 if (it.second.get_period_count() > 0) {
55 sorted[idx++] = it.first;
56 }
57 }
58
59 // Sort by period runtime (descending)
60 std::sort(sorted, sorted + count, [this](Component *a, Component *b) {
61 return this->component_stats_[a].get_period_time_ms() > this->component_stats_[b].get_period_time_ms();
62 });
63
64 // Log top components by period runtime
65 for (size_t i = 0; i < count; i++) {
66 const auto &stats = this->component_stats_[sorted[i]];
67 ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms",
68 LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_period_count(), stats.get_period_avg_time_ms(),
69 stats.get_period_max_time_ms(), stats.get_period_time_ms());
70 }
71
72 // Log total stats since boot (only for active components - idle ones haven't changed)
73 ESP_LOGI(TAG, " Total stats (since boot): %zu active components", count);
74
75 // Re-sort by total runtime for all-time stats
76 std::sort(sorted, sorted + count, [this](Component *a, Component *b) {
77 return this->component_stats_[a].get_total_time_ms() > this->component_stats_[b].get_total_time_ms();
78 });
79
80 for (size_t i = 0; i < count; i++) {
81 const auto &stats = this->component_stats_[sorted[i]];
82 ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms",
83 LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_total_count(), stats.get_total_avg_time_ms(),
84 stats.get_total_max_time_ms(), stats.get_total_time_ms());
85 }
86}
87
89 if (this->next_log_time_ == 0)
90 return;
91
92 if (current_time >= this->next_log_time_) {
93 this->log_stats_();
94 this->reset_stats_();
95 this->next_log_time_ = current_time + this->log_interval_;
96 }
97}
98
99} // namespace runtime_stats
100
102 nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
103
104} // namespace esphome
105
106#endif // USE_RUNTIME_STATS
Helper class for efficient buffer allocation - uses stack for small sizes, heap for large This is use...
Definition helpers.h:411
void record_component_time(Component *component, uint32_t duration_ms, uint32_t current_time)
std::map< Component *, ComponentRuntimeStats > component_stats_
void process_pending_stats(uint32_t current_time)
const Component * component
Definition component.cpp:37
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
runtime_stats::RuntimeStatsCollector * global_runtime_stats