From 2ab9df2a6744112ae0918fc53b95608b91df48e8 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Thu, 18 Jul 2024 20:10:34 -0400 Subject: [PATCH] Monitor and log memory heap fragmentation --- src/log.cpp | 32 +++++++++++++++++++------------- src/web.cpp | 39 ++++++++++++++++++++++++++++++--------- src/www/index.html | 12 ++++++++---- src/www/status.json | 4 ++++ 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/src/log.cpp b/src/log.cpp index 1eecb188..7e5af7f4 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -124,23 +124,29 @@ void printSavedLog(Print &outputDev) // These are defined in the linker script, and filled in by the elf2bin.py util extern "C" uint32_t __crc_len; extern "C" uint32_t __crc_val; +// Memory stats from the web.cpp file +extern "C" uint32_t free_heap; +extern "C" uint32_t max_block; +extern "C" uint8_t max_frag; void printMessageLog(Print &outputDev) { + ESP.getHeapStats(&free_heap, &max_block, &max_frag); + outputDev.write("Firmware Version: "); + outputDev.write(AUTO_VERSION); + outputDev.println(); + outputDev.write("Flash CRC: 0x"); + outputDev.println(__crc_val, 16); + outputDev.write("Flash Length: "); + outputDev.println(__crc_len); + outputDev.write("Free heap: "); + outputDev.println(free_heap); + outputDev.write("Max malloc size: "); + outputDev.println(max_block); + outputDev.write("Fragmentation pct: "); + outputDev.println(max_frag); + outputDev.println(); if (msgBuffer) { - static char buf[20] = ""; - outputDev.write("Firmware Version: "); - outputDev.write(AUTO_VERSION); - outputDev.println(); - outputDev.write("Flash CRC: "); - sprintf(buf, " 0x%08X", __crc_val); - outputDev.write(buf); - outputDev.println(); - outputDev.write("Flash Length: "); - sprintf(buf, "0x%X (%u)", __crc_len, __crc_len); - outputDev.write(buf); - outputDev.println(); - outputDev.println(); if (msgBuffer->wrapped != 0) { outputDev.write(&msgBuffer->buffer[msgBuffer->head], sizeof(msgBuffer->buffer) - msgBuffer->head); diff --git a/src/web.cpp b/src/web.cpp index 52b2c8cc..e4923913 100644 --- a/src/web.cpp +++ b/src/web.cpp @@ -131,7 +131,14 @@ const char www_pw_required_file[] = "www_pw_required_file"; // Control automatic reboot uint32_t rebootSeconds; // seconds between reboots const char system_reboot_timer[] = "system_reboot_timer"; -uint32_t min_heap = 0xffffffff; +// Track our memory usage +Ticker memoryMonitor; +uint32_t free_heap = 65535; +uint32_t min_heap = 65535; +uint32_t max_block = 65535; +uint8_t max_frag = 0; +uint32_t min_block = 65535; +uint8_t min_frag = 0; // Control WiFi physical layer mode WiFiPhyMode_t wifiPhyMode = (WiFiPhyMode_t)0; @@ -281,12 +288,21 @@ void web_loop() return; } server.handleClient(); +} - uint32_t free_heap = system_get_free_heap_size(); +void memory_ticker() +{ + ESP.getHeapStats(&free_heap, &max_block, &max_frag); if (free_heap < min_heap) { min_heap = free_heap; - RINFO("Free HEAP dropped to %d", min_heap); + RINFO("Minimum free heap dropped to %d", min_heap); + } + if (max_block < min_block) + { + min_block = max_block; + min_frag = max_frag; + RINFO("Maximum malloc block size dropped to %d (%d%% fragmented)", min_block, min_frag); } } @@ -351,6 +367,8 @@ void setup_web() subscription[i].clientIP = INADDR_NONE; subscription[i].clientUUID.clear(); } + // monitor memory heap once a second... + memoryMonitor.attach_scheduled(1.0, memory_ticker); RINFO("HTTP server started"); return; } @@ -557,12 +575,13 @@ void handle_status() ADD_BOOL(json, "garageObstructed", garage_door.obstructed); ADD_BOOL(json, "passwordRequired", passwordReq); ADD_INT(json, "rebootSeconds", rebootSeconds); - uint32_t free_heap = system_get_free_heap_size(); - if (free_heap < min_heap) - min_heap = free_heap; ADD_INT(json, "freeHeap", free_heap); ADD_INT(json, "minHeap", min_heap); ADD_INT(json, "minStack", ESP.getFreeContStack()); + ADD_INT(json, "maxBlock", max_block); + ADD_INT(json, "maxFrag", max_frag); + ADD_INT(json, "minBlock", min_block); + ADD_INT(json, "minFrag", min_frag); ADD_INT(json, "crashCount", crashCount); ADD_INT(json, "wifiPhyMode", wifiPhyMode); ADD_INT(json, "wifiPower", wifiPower); @@ -781,9 +800,6 @@ void SSEheartbeat(SSESubscription *s) // Serial.printf("Heartbeat\n"); if (!s) return; - uint32_t free_heap = system_get_free_heap_size(); - if (free_heap < min_heap) - min_heap = free_heap; if (!(s->clientIP)) return; @@ -814,6 +830,11 @@ void SSEheartbeat(SSESubscription *s) ADD_INT(json, "upTime", millis()); ADD_INT(json, "freeHeap", free_heap); ADD_INT(json, "minHeap", min_heap); + ADD_INT(json, "minStack", ESP.getFreeContStack()); + ADD_INT(json, "maxBlock", max_block); + ADD_INT(json, "maxFrag", max_frag); + ADD_INT(json, "minBlock", min_block); + ADD_INT(json, "minFrag", min_frag); ADD_STR(json, "wifiRSSI", (std::to_string(WiFi.RSSI()) + " dBm").c_str()); ADD_BOOL(json, "checkFlashCRC", flashCRC); END_JSON(json); diff --git a/src/www/index.html b/src/www/index.html index 2982f769..0889cc66 100644 --- a/src/www/index.html +++ b/src/www/index.html @@ -271,10 +271,14 @@


- - - - + + + + + + + +
freeHeap: 0minHeap: 0minStack: 0
freeHeap: 0 minHeap: 0 minStack: 0 
diff --git a/src/www/status.json b/src/www/status.json index 160a51fc..846a3fbb 100644 --- a/src/www/status.json +++ b/src/www/status.json @@ -20,6 +20,10 @@ "rebootSeconds": 0, "freeHeap": 20000, "minHeap": 10000, + "maxBlock": 19000, + "minBlock": 18000, + "maxFrag": 5, + "minFrag": 10, "minStack": 2000, "crashCount": 1, "wifiPhyMode": 0,