Add MemAudit: per-subsystem heap accounting in the boot log (#10900)

* Add MemAudit: per-subsystem heap accounting in the boot log

The 2.8.0 nRF52840 heap-exhaustion field reports had to be diagnosed by
hand, reconstructing each subsystem's heap footprint from source and
build flags one report at a time. This makes every future report
self-diagnosing from the serial log: a tiny fixed-size registry
(src/memory/MemAudit.*) that big long-lived allocations report into,
printed as one line at the end of setup() and alongside the periodic
"Heap free:" log:

  MemAudit[boot]: tmm=2500 warm=4000 pkthist=5824 nodedb=13440
  msgstore=2200 pktpool(live)=3270 total=31234

Instrumented: NodeDB hot vector (nodedb) + satellite maps (satmaps,
rb-tree overhead estimated), WarmNodeStore (warm), PacketHistory records
and hash index (pkthist), TrafficManagement caches (tmm/tmm_ni),
MessageStore text pool (msgstore), TFT line/repaint buffers (display),
and live in-flight packets (pktpool(live)) via an optional audit tag on
the packet pool allocator - the one hot path, counted with a relaxed
32-bit atomic add (single instructions on Cortex-M, no locks).

Cost: 128 B RAM for the 16-tag table, well under 1 KB flash on rak4631.
MESHTASTIC_MEM_AUDIT=0 compiles it out to inline no-op stubs (call
sites need no ifdefs); STM32WL, the tightest flash target, defaults off.

New native suite test_mem_audit covers add/set/snapshot arithmetic, tag
reuse (pointer and cross-TU strcmp fallback), null/unknown tags, and
table-full behavior; test/native-suite-count bumped to 28.

* native-wasm: add src/memory/ to the curated source filter

The wasm env denies all sources and adds an explicit file list; MemAudit
callers (main, MeshService, NodeDB, PacketHistory) are in that list but
src/memory/MemAudit.cpp was not, so wasm-ld failed on undefined
memaudit:: symbols.
This commit is contained in:
Ben Meadors
2026-07-06 13:18:49 -05:00
committed by GitHub
co-authored by GitHub
parent ed03a69555
commit 6c7ee8afc7
15 changed files with 440 additions and 7 deletions
+4
View File
@@ -1,5 +1,6 @@
#include "configuration.h"
#include "main.h"
#include "memory/MemAudit.h"
#if USE_TFTDISPLAY
#if ARCH_PORTDUINO
@@ -1228,6 +1229,7 @@ TFTDisplay::~TFTDisplay()
free(repaintChunkBuffer);
repaintChunkBuffer = nullptr;
}
memaudit::set("display", 0);
}
// Write the buffer to the display memory
@@ -1654,6 +1656,7 @@ bool TFTDisplay::connect()
LOG_ERROR("Not enough memory to create TFT line buffer\n");
return false;
}
memaudit::add("display", sizeof(uint16_t) * displayWidth);
}
if (this->repaintChunkBuffer == NULL) {
this->repaintChunkBuffer = (uint16_t *)malloc(sizeof(uint16_t) * displayWidth * kFullRepaintChunkRows);
@@ -1662,6 +1665,7 @@ bool TFTDisplay::connect()
LOG_ERROR("Not enough memory to create TFT repaint chunk buffer\n");
return false;
}
memaudit::add("display", sizeof(uint16_t) * displayWidth * kFullRepaintChunkRows);
}
return true;
}