1
0
mirror of https://github.com/esphome/esphome.git synced 2025-06-15 06:46:59 +02:00

[globals] Prevent redundant oversized string checks in loop (#9001)

Co-authored-by: J. Nick Koston <nick+github@koston.org>
This commit is contained in:
Edward Firmo 2025-06-09 18:19:24 +02:00 committed by GitHub
parent b7ca6e087a
commit ce4371a80d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -39,7 +39,7 @@ template<typename T> class RestoringGlobalsComponent : public Component {
void setup() override {
this->rtc_ = global_preferences->make_preference<T>(1944399030U ^ this->name_hash_);
this->rtc_.load(&this->value_);
memcpy(&this->prev_value_, &this->value_, sizeof(T));
memcpy(&this->last_checked_value_, &this->value_, sizeof(T));
}
float get_setup_priority() const override { return setup_priority::HARDWARE; }
@ -52,15 +52,15 @@ template<typename T> class RestoringGlobalsComponent : public Component {
protected:
void store_value_() {
int diff = memcmp(&this->value_, &this->prev_value_, sizeof(T));
int diff = memcmp(&this->value_, &this->last_checked_value_, sizeof(T));
if (diff != 0) {
this->rtc_.save(&this->value_);
memcpy(&this->prev_value_, &this->value_, sizeof(T));
memcpy(&this->last_checked_value_, &this->value_, sizeof(T));
}
}
T value_{};
T prev_value_{};
T last_checked_value_{};
uint32_t name_hash_{};
ESPPreferenceObject rtc_;
};
@ -85,7 +85,7 @@ template<typename T, uint8_t SZ> class RestoringGlobalStringComponent : public C
if (hasdata) {
this->value_.assign(temp + 1, temp[0]);
}
this->prev_value_.assign(this->value_);
this->last_checked_value_.assign(this->value_);
}
float get_setup_priority() const override { return setup_priority::HARDWARE; }
@ -98,13 +98,12 @@ template<typename T, uint8_t SZ> class RestoringGlobalStringComponent : public C
protected:
void store_value_() {
int diff = this->value_.compare(this->prev_value_);
int diff = this->value_.compare(this->last_checked_value_);
if (diff != 0) {
// Make it into a length prefixed thing
unsigned char temp[SZ];
// If string is bigger than the allocation, do not save it.
// We don't need to waste ram setting prev_value either.
int size = this->value_.size();
// Less than, not less than or equal, SZ includes the length byte.
if (size < SZ) {
@ -112,13 +111,17 @@ template<typename T, uint8_t SZ> class RestoringGlobalStringComponent : public C
// SZ should be pre checked at the schema level, it can't go past the char range.
temp[0] = ((unsigned char) size);
this->rtc_.save(&temp);
this->prev_value_.assign(this->value_);
}
// Always update last_checked_value_ to match current value, even for oversized strings.
// This prevents redundant size checks on every loop iteration when a string remains oversized.
// Without this, the diff != 0 check would pass repeatedly for the same oversized string,
// wasting CPU cycles on size comparisons.
this->last_checked_value_.assign(this->value_);
}
}
T value_{};
T prev_value_{};
T last_checked_value_{};
uint32_t name_hash_{};
ESPPreferenceObject rtc_;
};