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: 0 |
- minHeap: 0 |
- minStack: 0 |
+
+ freeHeap: 0 |
+ minHeap: 0 |
+ minStack: 0 |
+
+
+ maxBlock: 0 (0%) |
+ minBlock: 0 (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,