From b3983bc088d43d223c4f14aacdc698238b06310e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 24 Feb 2026 13:19:53 -0600 Subject: [PATCH] [core] Pass std::function by rvalue reference in set_timer_common_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change set_timer_common_ to take std::function&& instead of by value. This avoids materializing a std::function copy on the stack at each call site — the caller just passes a pointer to the rvalue. On BK7231N (Thumb-1), each forwarder (set_timeout, set_interval) was 118 bytes due to the inlined std::function move constructor + register spilling. With rvalue reference, they shrink to 32 bytes each. All 12 callers already pass rvalues (std::move or lambda temporaries), so this is a purely mechanical change with no semantic difference. BK7231N: forwarders 118 -> 32 bytes each, ~258 bytes saved total ESP32: forwarders 46 -> 30 bytes each, ~20 bytes saved total --- esphome/core/scheduler.cpp | 2 +- esphome/core/scheduler.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index e4e0751e10..fab54eb648 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -135,7 +135,7 @@ bool Scheduler::is_retry_cancelled_locked_(Component *component, NameType name_t // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, const char *static_name, uint32_t hash_or_id, uint32_t delay, - std::function func, bool is_retry, bool skip_cancel) { + std::function &&func, bool is_retry, bool skip_cancel) { if (delay == SCHEDULER_DONT_RUN) { // Still need to cancel existing timer if we have a name/id if (!skip_cancel) { diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index ed457b87f6..1ed897a7e4 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -255,7 +255,7 @@ class Scheduler { // Common implementation for both timeout and interval // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id void set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, const char *static_name, - uint32_t hash_or_id, uint32_t delay, std::function func, bool is_retry = false, + uint32_t hash_or_id, uint32_t delay, std::function &&func, bool is_retry = false, bool skip_cancel = false); // Common implementation for retry - Remove before 2026.8.0