From f2c827f9a2395ac34144bddbb3f9a3edd4c43bd0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 16 Feb 2026 08:08:43 -0600 Subject: [PATCH 1/4] [runtime_image] Remove stored RAMAllocator member (#13998) --- esphome/components/runtime_image/png_decoder.cpp | 6 ++++-- esphome/components/runtime_image/png_decoder.h | 1 - esphome/components/runtime_image/runtime_image.cpp | 8 +++++--- esphome/components/runtime_image/runtime_image.h | 1 - 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/esphome/components/runtime_image/png_decoder.cpp b/esphome/components/runtime_image/png_decoder.cpp index 9fe4a9c4ff..591504328d 100644 --- a/esphome/components/runtime_image/png_decoder.cpp +++ b/esphome/components/runtime_image/png_decoder.cpp @@ -50,7 +50,8 @@ static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, ui PngDecoder::PngDecoder(RuntimeImage *image) : ImageDecoder(image) { { - pngle_t *pngle = this->allocator_.allocate(1, PNGLE_T_SIZE); + RAMAllocator allocator; + pngle_t *pngle = allocator.allocate(1, PNGLE_T_SIZE); if (!pngle) { ESP_LOGE(TAG, "Failed to allocate memory for PNGLE engine!"); return; @@ -64,7 +65,8 @@ PngDecoder::PngDecoder(RuntimeImage *image) : ImageDecoder(image) { PngDecoder::~PngDecoder() { if (this->pngle_) { pngle_reset(this->pngle_); - this->allocator_.deallocate(this->pngle_, PNGLE_T_SIZE); + RAMAllocator allocator; + allocator.deallocate(this->pngle_, PNGLE_T_SIZE); } } diff --git a/esphome/components/runtime_image/png_decoder.h b/esphome/components/runtime_image/png_decoder.h index b5c1e70c2a..24521d33a8 100644 --- a/esphome/components/runtime_image/png_decoder.h +++ b/esphome/components/runtime_image/png_decoder.h @@ -29,7 +29,6 @@ class PngDecoder : public ImageDecoder { uint32_t get_pixels_decoded() const { return this->pixels_decoded_; } protected: - RAMAllocator allocator_; pngle_t *pngle_{nullptr}; uint32_t pixels_decoded_{0}; }; diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp index 1d70f38d6b..603ea76f01 100644 --- a/esphome/components/runtime_image/runtime_image.cpp +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -230,7 +230,8 @@ void RuntimeImage::release() { void RuntimeImage::release_buffer_() { if (this->buffer_) { ESP_LOGV(TAG, "Releasing buffer of size %zu", this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); - this->allocator_.deallocate(this->buffer_, this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); + RAMAllocator allocator; + allocator.deallocate(this->buffer_, this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); this->buffer_ = nullptr; this->data_start_ = nullptr; this->width_ = 0; @@ -254,11 +255,12 @@ size_t RuntimeImage::resize_buffer_(int width, int height) { } ESP_LOGD(TAG, "Allocating buffer: %dx%d, %zu bytes", width, height, new_size); - this->buffer_ = this->allocator_.allocate(new_size); + RAMAllocator allocator; + this->buffer_ = allocator.allocate(new_size); if (!this->buffer_) { ESP_LOGE(TAG, "Failed to allocate %zu bytes. Largest free block: %zu", new_size, - this->allocator_.get_max_free_block_size()); + allocator.get_max_free_block_size()); return 0; } diff --git a/esphome/components/runtime_image/runtime_image.h b/esphome/components/runtime_image/runtime_image.h index 0a5279d86d..4bdcdcac9e 100644 --- a/esphome/components/runtime_image/runtime_image.h +++ b/esphome/components/runtime_image/runtime_image.h @@ -165,7 +165,6 @@ class RuntimeImage : public image::Image { std::unique_ptr create_decoder_(); // Memory management - RAMAllocator allocator_{}; uint8_t *buffer_{nullptr}; // Decoder management From ffb9a00e2683d6ad0aad47fc4c6a783ca615e101 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 16 Feb 2026 08:09:13 -0600 Subject: [PATCH 2/4] [online_image] Remove stored RAMAllocator member from DownloadBuffer (#13999) --- esphome/components/online_image/download_buffer.cpp | 10 ++++++---- esphome/components/online_image/download_buffer.h | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/online_image/download_buffer.cpp b/esphome/components/online_image/download_buffer.cpp index 999005df82..2ec6365aa1 100644 --- a/esphome/components/online_image/download_buffer.cpp +++ b/esphome/components/online_image/download_buffer.cpp @@ -7,7 +7,8 @@ namespace esphome::online_image { static const char *const TAG = "online_image.download_buffer"; DownloadBuffer::DownloadBuffer(size_t size) : size_(size) { - this->buffer_ = this->allocator_.allocate(size); + RAMAllocator allocator; + this->buffer_ = allocator.allocate(size); this->reset(); if (!this->buffer_) { ESP_LOGE(TAG, "Initial allocation of download buffer failed!"); @@ -38,15 +39,16 @@ size_t DownloadBuffer::resize(size_t size) { // Avoid useless reallocations; if the buffer is big enough, don't reallocate. return this->size_; } - this->allocator_.deallocate(this->buffer_, this->size_); - this->buffer_ = this->allocator_.allocate(size); + RAMAllocator allocator; + allocator.deallocate(this->buffer_, this->size_); + this->buffer_ = allocator.allocate(size); this->reset(); if (this->buffer_) { this->size_ = size; return size; } else { ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", size, - this->allocator_.get_max_free_block_size()); + allocator.get_max_free_block_size()); this->size_ = 0; return 0; } diff --git a/esphome/components/online_image/download_buffer.h b/esphome/components/online_image/download_buffer.h index 110a4b608a..73061b23b5 100644 --- a/esphome/components/online_image/download_buffer.h +++ b/esphome/components/online_image/download_buffer.h @@ -15,7 +15,10 @@ namespace esphome::online_image { class DownloadBuffer { public: DownloadBuffer(size_t size); - ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); } + ~DownloadBuffer() { + RAMAllocator allocator; + allocator.deallocate(this->buffer_, this->size_); + } uint8_t *data(size_t offset = 0); uint8_t *append() { return this->data(this->unread_); } @@ -34,7 +37,6 @@ class DownloadBuffer { size_t resize(size_t size); protected: - RAMAllocator allocator_{}; uint8_t *buffer_; size_t size_; /** Total number of downloaded bytes not yet read. */ From 81872d9822d1930e2408110acfcdb8e8e3dfd95a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 16 Feb 2026 08:09:26 -0600 Subject: [PATCH 3/4] [camera, camera_encoder] Remove stored RAMAllocator member (#13997) --- esphome/components/camera/buffer_impl.cpp | 12 ++++++++---- esphome/components/camera/buffer_impl.h | 1 - .../camera_encoder/encoder_buffer_impl.cpp | 9 ++++++--- .../components/camera_encoder/encoder_buffer_impl.h | 1 - 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/esphome/components/camera/buffer_impl.cpp b/esphome/components/camera/buffer_impl.cpp index d17a4e2707..97cdd2e104 100644 --- a/esphome/components/camera/buffer_impl.cpp +++ b/esphome/components/camera/buffer_impl.cpp @@ -3,18 +3,22 @@ namespace esphome::camera { BufferImpl::BufferImpl(size_t size) { - this->data_ = this->allocator_.allocate(size); + RAMAllocator allocator; + this->data_ = allocator.allocate(size); this->size_ = size; } BufferImpl::BufferImpl(CameraImageSpec *spec) { - this->data_ = this->allocator_.allocate(spec->bytes_per_image()); + RAMAllocator allocator; + this->data_ = allocator.allocate(spec->bytes_per_image()); this->size_ = spec->bytes_per_image(); } BufferImpl::~BufferImpl() { - if (this->data_ != nullptr) - this->allocator_.deallocate(this->data_, this->size_); + if (this->data_ != nullptr) { + RAMAllocator allocator; + allocator.deallocate(this->data_, this->size_); + } } } // namespace esphome::camera diff --git a/esphome/components/camera/buffer_impl.h b/esphome/components/camera/buffer_impl.h index 46398295fa..5e42df7957 100644 --- a/esphome/components/camera/buffer_impl.h +++ b/esphome/components/camera/buffer_impl.h @@ -18,7 +18,6 @@ class BufferImpl : public Buffer { ~BufferImpl() override; protected: - RAMAllocator allocator_; size_t size_{}; uint8_t *data_{}; }; diff --git a/esphome/components/camera_encoder/encoder_buffer_impl.cpp b/esphome/components/camera_encoder/encoder_buffer_impl.cpp index db84026496..f12c66f203 100644 --- a/esphome/components/camera_encoder/encoder_buffer_impl.cpp +++ b/esphome/components/camera_encoder/encoder_buffer_impl.cpp @@ -4,7 +4,8 @@ namespace esphome::camera_encoder { bool EncoderBufferImpl::set_buffer_size(size_t size) { if (size > this->capacity_) { - uint8_t *p = this->allocator_.reallocate(this->data_, size); + RAMAllocator allocator; + uint8_t *p = allocator.reallocate(this->data_, size); if (p == nullptr) return false; @@ -16,8 +17,10 @@ bool EncoderBufferImpl::set_buffer_size(size_t size) { } EncoderBufferImpl::~EncoderBufferImpl() { - if (this->data_ != nullptr) - this->allocator_.deallocate(this->data_, this->capacity_); + if (this->data_ != nullptr) { + RAMAllocator allocator; + allocator.deallocate(this->data_, this->capacity_); + } } } // namespace esphome::camera_encoder diff --git a/esphome/components/camera_encoder/encoder_buffer_impl.h b/esphome/components/camera_encoder/encoder_buffer_impl.h index 13eccb7d56..d394daff14 100644 --- a/esphome/components/camera_encoder/encoder_buffer_impl.h +++ b/esphome/components/camera_encoder/encoder_buffer_impl.h @@ -16,7 +16,6 @@ class EncoderBufferImpl : public camera::EncoderBuffer { ~EncoderBufferImpl() override; protected: - RAMAllocator allocator_; size_t capacity_{}; size_t size_{}; uint8_t *data_{}; From 0c4827d348e4f55807fa910490e59144711ef392 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 16 Feb 2026 08:09:53 -0600 Subject: [PATCH 4/4] [json, core] Remove stored RAMAllocator, make constructors constexpr (#14000) --- esphome/components/json/json_util.h | 11 ++++++----- esphome/core/helpers.h | 11 ++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index ca074926bd..c472b9a9ec 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -18,7 +18,10 @@ namespace json { // Build an allocator for the JSON Library using the RAMAllocator class // This is only compiled when PSRAM is enabled struct SpiRamAllocator : ArduinoJson::Allocator { - void *allocate(size_t size) override { return allocator_.allocate(size); } + void *allocate(size_t size) override { + RAMAllocator allocator; + return allocator.allocate(size); + } void deallocate(void *ptr) override { // ArduinoJson's Allocator interface doesn't provide the size parameter in deallocate. @@ -31,11 +34,9 @@ struct SpiRamAllocator : ArduinoJson::Allocator { } void *reallocate(void *ptr, size_t new_size) override { - return allocator_.reallocate(static_cast(ptr), new_size); + RAMAllocator allocator; + return allocator.reallocate(static_cast(ptr), new_size); } - - protected: - RAMAllocator allocator_{RAMAllocator::NONE}; }; #endif diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 34c7452484..298b93fbc4 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1673,13 +1673,10 @@ template class RAMAllocator { ALLOW_FAILURE = 1 << 2, // Does nothing. Kept for compatibility. }; - RAMAllocator() = default; - RAMAllocator(uint8_t flags) { - // default is both external and internal - flags &= ALLOC_INTERNAL | ALLOC_EXTERNAL; - if (flags != 0) - this->flags_ = flags; - } + constexpr RAMAllocator() = default; + constexpr RAMAllocator(uint8_t flags) + : flags_((flags & (ALLOC_INTERNAL | ALLOC_EXTERNAL)) != 0 ? (flags & (ALLOC_INTERNAL | ALLOC_EXTERNAL)) + : (ALLOC_INTERNAL | ALLOC_EXTERNAL)) {} template constexpr RAMAllocator(const RAMAllocator &other) : flags_{other.flags_} {} T *allocate(size_t n) { return this->allocate(n, sizeof(T)); }