mirror of
https://github.com/esphome/esphome.git
synced 2026-09-14 16:48:40 +00:00
[ota] Pack deferred state args into uint32 to avoid heap allocation
The notify_state_deferred_ lambda captured [this, state, progress, error] (16 bytes on 32-bit), exceeding std::function SBO and forcing a heap allocation on every OTA progress update. Pack the three values into a single uint32_t: - state (8 bits) + error (8 bits) + progress as fixed-point (16 bits) The lambda now captures [this, packed] (8 bytes), fitting in SBO. Progress resolution of 0.01% is more than adequate for OTA reporting.
This commit is contained in:
@@ -74,7 +74,15 @@ class OTAComponent : public Component {
|
||||
* (like web_server OTA) to ensure listeners execute in the main loop.
|
||||
*/
|
||||
void notify_state_deferred_(OTAState state, float progress, uint8_t error) {
|
||||
this->defer([this, state, progress, error]() { this->notify_state_(state, progress, error); });
|
||||
// Pack state, error, and progress into a single uint32_t so the lambda
|
||||
// captures only [this, packed] (8 bytes) — fits in std::function SBO.
|
||||
// Layout: [state:8][error:8][progress_fixed:16] where progress is 0–10000 (0.01% resolution)
|
||||
uint32_t packed = (static_cast<uint32_t>(state) << 24) | (static_cast<uint32_t>(error) << 16) |
|
||||
static_cast<uint16_t>(progress * 100.0f);
|
||||
this->defer([this, packed]() {
|
||||
this->notify_state_(static_cast<OTAState>(packed >> 24), static_cast<float>(packed & 0xFFFF) / 100.0f,
|
||||
static_cast<uint8_t>(packed >> 16));
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<OTAStateListener *> state_listeners_;
|
||||
|
||||
Reference in New Issue
Block a user