From 23fc99f0fea634d8dc39e74550bde15a366bd11e Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 25 Apr 2026 12:00:13 -0500 Subject: [PATCH] [MEM] Heap-allocate createDiscovery JsonDocuments (#2302) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit createDiscovery sits at the bottom of the discovery call chain (loop → launchBTDiscovery → Discovery → createDiscoveryFromList (9-col, VLA) → createDiscoveryFromList(13-col) → here). Keeping 2×1024 B StaticJsonDocuments on the stack burned loopTask headroom down to ~100 B free under a full BLE + WebUI load. Moving the two buffers to the heap drops that 2 KB off the stack peak. Measured over the full test_perf + test_webui suite on esp32dev-ble-hil-fastsys (dev HEAD): freestck_min_bytes: 292 → 2324 B (+2032, target was ≥1500) minmem_soak_bytes: 18200 → 20652 B (+2452) all 17 tests still pass The docs are function-scoped, so net heap usage is unchanged long-term (free-on-return), and the soak heap floor actually improved. Co-authored-by: Claude Opus 4.7 (1M context) --- main/mqttDiscovery.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/main/mqttDiscovery.cpp b/main/mqttDiscovery.cpp index a36a2cf..869aa56 100644 --- a/main/mqttDiscovery.cpp +++ b/main/mqttDiscovery.cpp @@ -451,7 +451,13 @@ void createDiscovery(const char* sensor_type, const char* device_name, const char* device_manufacturer, const char* device_model, const char* device_id, bool retainCmd, const char* state_class, const char* state_off, const char* state_on, const char* enum_options, const char* command_template, bool diagnostic_entity) { - StaticJsonDocument jsonBuffer; + // Heap-allocate the two JsonDocuments: createDiscovery sits at the bottom of + // a deep call chain (loop → launchBTDiscovery → Discovery → + // createDiscoveryFromList(9-col, VLA) → createDiscoveryFromList(13-col) → + // here). Keeping 2×1024 B on the stack burned loopTask's stack headroom + // down to ~100 B free under full perf load. Heap-backed docs drop that + // 2 KB off the peak. + DynamicJsonDocument jsonBuffer(JSON_MSG_BUFFER); JsonObject sensor = jsonBuffer.to(); // If a component cannot render it's state (f.i. KAKU relays) no state topic @@ -608,7 +614,7 @@ void createDiscovery(const char* sensor_type, sensor["ops"] = enum_options; // options } - StaticJsonDocument jsonDeviceBuffer; + DynamicJsonDocument jsonDeviceBuffer(JSON_MSG_BUFFER); JsonObject device = jsonDeviceBuffer.to(); JsonArray identifiers = device.createNestedArray("ids");