mirror of
https://github.com/esphome/esphome.git
synced 2026-02-28 09:54:19 -07:00
[core] Optimize WarnIfComponentBlockingGuard::finish() hot path
Split the rarely-taken warning path into a separate noinline cold function so the hot path (called every component every loop iteration) is minimal. Also make WARN_IF_BLOCKING_OVER_MS constexpr so the compiler uses an immediate compare instead of a memory load, and merge the two ESP_LOGW calls into one. finish() shrinks from 108 to 30 bytes. Total flash savings: -116 bytes.
This commit is contained in:
@@ -107,8 +107,8 @@ const uint8_t STATUS_LED_OK = 0x00;
|
||||
const uint8_t STATUS_LED_WARNING = 0x08; // Bit 3
|
||||
const uint8_t STATUS_LED_ERROR = 0x10; // Bit 4
|
||||
|
||||
const uint16_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning
|
||||
const uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again
|
||||
static constexpr uint16_t WARN_IF_BLOCKING_INCREMENT_MS =
|
||||
10U; ///< How long the blocking time must be larger to warn again
|
||||
|
||||
uint32_t global_state = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
@@ -556,37 +556,35 @@ void PollingComponent::stop_poller() {
|
||||
uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; }
|
||||
void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
|
||||
|
||||
WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component, uint32_t start_time)
|
||||
: started_(start_time), component_(component) {}
|
||||
static void __attribute__((noinline, cold)) warn_blocking(Component *component, uint32_t blocking_time) {
|
||||
bool should_warn;
|
||||
if (component != nullptr) {
|
||||
should_warn = component->should_warn_of_blocking(blocking_time);
|
||||
} else {
|
||||
should_warn = true; // Already checked > WARN_IF_BLOCKING_OVER_MS in caller
|
||||
}
|
||||
if (should_warn) {
|
||||
ESP_LOGW(TAG, "%s took a long time for an operation (%" PRIu32 " ms), max is 30 ms",
|
||||
component == nullptr ? LOG_STR_LITERAL("<null>") : LOG_STR_ARG(component->get_component_log_str()),
|
||||
blocking_time);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t WarnIfComponentBlockingGuard::finish() {
|
||||
uint32_t curr_time = millis();
|
||||
|
||||
uint32_t blocking_time = curr_time - this->started_;
|
||||
|
||||
#ifdef USE_RUNTIME_STATS
|
||||
// Record component runtime stats
|
||||
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) {
|
||||
should_warn = this->component_->should_warn_of_blocking(blocking_time);
|
||||
} else {
|
||||
should_warn = blocking_time > WARN_IF_BLOCKING_OVER_MS;
|
||||
if (blocking_time > WARN_IF_BLOCKING_OVER_MS) {
|
||||
warn_blocking(this->component_, blocking_time);
|
||||
}
|
||||
if (should_warn) {
|
||||
ESP_LOGW(TAG, "%s took a long time for an operation (%" PRIu32 " ms)",
|
||||
component_ == nullptr ? LOG_STR_LITERAL("<null>") : LOG_STR_ARG(component_->get_component_log_str()),
|
||||
blocking_time);
|
||||
ESP_LOGW(TAG, "Components should block for at most 30 ms");
|
||||
}
|
||||
|
||||
return curr_time;
|
||||
}
|
||||
|
||||
WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {}
|
||||
|
||||
void clear_setup_priority_overrides() {
|
||||
// Free the setup priority map completely
|
||||
delete setup_priority_overrides;
|
||||
|
||||
@@ -79,7 +79,7 @@ extern const uint8_t STATUS_LED_ERROR;
|
||||
// Remove before 2026.8.0
|
||||
enum class RetryResult { DONE, RETRY };
|
||||
|
||||
extern const uint16_t WARN_IF_BLOCKING_OVER_MS;
|
||||
inline constexpr uint16_t WARN_IF_BLOCKING_OVER_MS = 50U;
|
||||
|
||||
class Component {
|
||||
public:
|
||||
@@ -550,12 +550,13 @@ class PollingComponent : public Component {
|
||||
|
||||
class WarnIfComponentBlockingGuard {
|
||||
public:
|
||||
WarnIfComponentBlockingGuard(Component *component, uint32_t start_time);
|
||||
WarnIfComponentBlockingGuard(Component *component, uint32_t start_time)
|
||||
: started_(start_time), component_(component) {}
|
||||
|
||||
// Finish the timing operation and return the current time
|
||||
uint32_t finish();
|
||||
|
||||
~WarnIfComponentBlockingGuard();
|
||||
~WarnIfComponentBlockingGuard() = default;
|
||||
|
||||
protected:
|
||||
uint32_t started_;
|
||||
|
||||
Reference in New Issue
Block a user