From 7fc5bfd787794431cc386c6f1be09b42fef51d0e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 23 Jun 2025 04:09:34 +0200 Subject: [PATCH] Reduce RAM usage for scheduled tasks (#9180) --- esphome/core/scheduler.cpp | 4 ++++ esphome/core/scheduler.h | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index eed222c974..8144435163 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -319,13 +319,17 @@ bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, return ret; } uint64_t Scheduler::millis_() { + // Get the current 32-bit millis value const uint32_t now = millis(); + // Check for rollover by comparing with last value if (now < this->last_millis_) { + // Detected rollover (happens every ~49.7 days) this->millis_major_++; ESP_LOGD(TAG, "Incrementing scheduler major at %" PRIu64 "ms", now + (static_cast(this->millis_major_) << 32)); } this->last_millis_ = now; + // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time return now + (static_cast(this->millis_major_) << 32); } diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 872a8bd6f6..1284bcd4a7 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -29,12 +29,16 @@ class Scheduler { protected: struct SchedulerItem { + // Ordered by size to minimize padding Component *component; - std::string name; - enum Type { TIMEOUT, INTERVAL } type; uint32_t interval; + // 64-bit time to handle millis() rollover. The scheduler combines the 32-bit millis() + // with a 16-bit rollover counter to create a 64-bit time that won't roll over for + // billions of years. This ensures correct scheduling even when devices run for months. uint64_t next_execution_; + std::string name; std::function callback; + enum Type : uint8_t { TIMEOUT, INTERVAL } type; bool remove; static bool cmp(const std::unique_ptr &a, const std::unique_ptr &b);