From a1009f7a5c423dfa613b045ca09f3b77681480f6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 17 Mar 2026 01:51:33 -1000 Subject: [PATCH] Use relaxed memory ordering for all counter atomics The mutex already provides all necessary memory ordering for the counter operations. acquire/release fences on the fast-path reads were causing unnecessary cache flushes, regressing Scheduler_NextScheduleIn by ~10%. --- esphome/core/scheduler.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index f0589bef24..d00673f403 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -540,7 +540,7 @@ class Scheduler { // Lock-free check if to_add_ is empty (for fast-path in process_to_add) bool to_add_empty_() const { #ifdef ESPHOME_THREAD_MULTI_ATOMICS - return this->to_add_count_.load(std::memory_order_acquire) == 0; + return this->to_add_count_.load(std::memory_order_relaxed) == 0; #elif defined(ESPHOME_THREAD_SINGLE) // Single-threaded: no concurrent writers, direct check is safe return this->to_add_.empty(); @@ -553,7 +553,7 @@ class Scheduler { // Increment to_add_count_ (caller must hold lock on non-atomic platforms) void to_add_count_increment_() { #ifdef ESPHOME_THREAD_MULTI_ATOMICS - this->to_add_count_.fetch_add(1, std::memory_order_release); + this->to_add_count_.fetch_add(1, std::memory_order_relaxed); #else this->to_add_count_++; #endif @@ -586,7 +586,7 @@ class Scheduler { // defer_queue_ only exists on multi-threaded platforms, so no ESPHOME_THREAD_SINGLE path // ESPHOME_THREAD_MULTI_NO_ATOMICS: always take the lock #ifdef ESPHOME_THREAD_MULTI_ATOMICS - return this->defer_count_.load(std::memory_order_acquire) == 0; + return this->defer_count_.load(std::memory_order_relaxed) == 0; #else return false; #endif @@ -594,7 +594,7 @@ class Scheduler { void defer_count_increment_() { #ifdef ESPHOME_THREAD_MULTI_ATOMICS - this->defer_count_.fetch_add(1, std::memory_order_release); + this->defer_count_.fetch_add(1, std::memory_order_relaxed); #else this->defer_count_++; #endif @@ -621,7 +621,7 @@ class Scheduler { // Lock-free check if there are items to remove (for fast-path in cleanup_) bool to_remove_empty_() const { #ifdef ESPHOME_THREAD_MULTI_ATOMICS - return this->to_remove_.load(std::memory_order_acquire) == 0; + return this->to_remove_.load(std::memory_order_relaxed) == 0; #elif defined(ESPHOME_THREAD_SINGLE) return this->to_remove_ == 0; #else @@ -631,7 +631,7 @@ class Scheduler { void to_remove_add_(uint32_t count) { #ifdef ESPHOME_THREAD_MULTI_ATOMICS - this->to_remove_.fetch_add(count, std::memory_order_release); + this->to_remove_.fetch_add(count, std::memory_order_relaxed); #else this->to_remove_ += count; #endif