diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index c9ed69a80c..2cf6644c3e 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -914,6 +914,16 @@ void Scheduler::trim_freelist() { } this->scheduler_item_pool_head_ = nullptr; this->scheduler_item_pool_size_ = 0; + + // The vectors that back items_/to_add_/defer_queue_ also retain their boot-peak + // capacity (std::vector grows by doubling). Swap each with a same-content copy to + // reclaim the slack -- the new vector is sized exactly to its current contents. + std::vector(this->items_).swap(this->items_); + std::vector(this->to_add_).swap(this->to_add_); +#ifndef ESPHOME_THREAD_SINGLE + std::vector(this->defer_queue_).swap(this->defer_queue_); +#endif + #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Freelist trimmed (%zu items freed)", freed); #else diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index da15279ae9..7cdb29aae0 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -132,11 +132,10 @@ class Scheduler { // @return Timestamp of the last item that ran, or `now` unchanged if none ran. uint32_t call(uint32_t now); - // Free every SchedulerItem currently sitting in the recycle freelist. Items in - // items_/to_add_/defer_queue_ are untouched. Intended to claim the post-boot - // peak: boot churn (component setup, first sensor reads, retries) inflates the - // freelist beyond what steady-state needs, and without a one-shot trim that - // peak would be retained forever. + // Reclaim memory held by the post-boot peak. Frees every SchedulerItem in the + // recycle freelist and shrinks items_/to_add_/defer_queue_ vector capacity to + // their current sizes (std::vector grows by doubling and otherwise retains the + // peak). Live items in those vectors are preserved. void trim_freelist(); // Move items from to_add_ into the main heap.