From 0594e22e3a8b144ed0c2d673369878c1ef8819e1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 18 Mar 2026 16:08:24 -1000 Subject: [PATCH] [preferences] Compile out loop() when flash_write_interval is non-zero The write_interval == 0 case (sync every loop) is only used on host or for testing. For the vast majority of real devices using the default 60s interval, loop() and the runtime branch are unnecessary overhead. Use a compile-time define to separate the two modes so that: - Normal case: no loop() override, no write_interval_ member, just set_interval - Zero interval case: loop() syncs every iteration, no interval needed --- esphome/components/preferences/__init__.py | 6 +++++- esphome/components/preferences/syncer.h | 17 +++++++---------- esphome/core/defines.h | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/esphome/components/preferences/__init__.py b/esphome/components/preferences/__init__.py index c6bede891ab..b5af7c05500 100644 --- a/esphome/components/preferences/__init__.py +++ b/esphome/components/preferences/__init__.py @@ -21,5 +21,9 @@ CONFIG_SCHEMA = cv.Schema( @coroutine_with_priority(CoroPriority.PREFERENCES) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - cg.add(var.set_write_interval(config[CONF_FLASH_WRITE_INTERVAL])) + write_interval = config[CONF_FLASH_WRITE_INTERVAL] + if write_interval == 0: + cg.add_define("USE_PREFERENCES_SYNC_EVERY_LOOP") + else: + cg.add(var.set_write_interval(write_interval)) await cg.register_component(var, config) diff --git a/esphome/components/preferences/syncer.h b/esphome/components/preferences/syncer.h index 96716d3f304..e28cc8c8d54 100644 --- a/esphome/components/preferences/syncer.h +++ b/esphome/components/preferences/syncer.h @@ -8,24 +8,21 @@ namespace preferences { class IntervalSyncer final : public Component { public: +#ifdef USE_PREFERENCES_SYNC_EVERY_LOOP + void loop() override { global_preferences->sync(); } +#else void set_write_interval(uint32_t write_interval) { this->write_interval_ = write_interval; } void setup() override { - if (this->write_interval_ != 0) { - set_interval(this->write_interval_, []() { global_preferences->sync(); }); - // When using interval-based syncing, we don't need the loop - this->disable_loop(); - } - } - void loop() override { - if (this->write_interval_ == 0) { - global_preferences->sync(); - } + this->set_interval(this->write_interval_, []() { global_preferences->sync(); }); } +#endif void on_shutdown() override { global_preferences->sync(); } float get_setup_priority() const override { return setup_priority::BUS; } +#ifndef USE_PREFERENCES_SYNC_EVERY_LOOP protected: uint32_t write_interval_{60000}; +#endif }; } // namespace preferences diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 09269ea1b4d..01f33f936f1 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -117,6 +117,7 @@ #define USE_NUMBER #define USE_OUTPUT #define USE_POWER_SUPPLY +#define USE_PREFERENCES_SYNC_EVERY_LOOP #define USE_QR_CODE #define USE_SAFE_MODE_CALLBACK #define USE_SELECT