Bench instrumentation: one flag, console and loop timing

-DMESHTASTIC_BENCH_INSTRUMENTATION=1 (default 0) turns on the loss bench's
diagnostic logging, set up in src/BenchInstrumentation.h. It changes no
behaviour, only adds lines and their cost. This part sets:

- MESHTASTIC_LOG_RECORD_MILLIS: API log records carry "millis=<uptime> "
  (a radio task line's own logging time), and console lines print ms.
- MESHTASTIC_SLOW_THREAD_MS (10): "Thread <name> ran <n> ms".
- MESHTASTIC_LOG_USB_STATS: console bytes and log records the port takes
  and refuses, every 10 s; USB stalls of 1 s or more, with the HWCDC
  registers on ESP32-S3 and the TX latch kicks kickLatchedTx() makes;
  the loop's radio upkeep timing.

With the radio task it also logs the task's unused stack at each upkeep.

Co-Authored-By: Jonathan Bennett <jbennett@incomsystems.biz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REkPVFh6kvG4AZJ5A8AtM9
This commit is contained in:
Jonathan BennettandClaude Opus 5.5 committed 2026-10-10 15:25:15 +00:00
1 parent 27339a6b01
commit 94ab80fbc5
11 files changed
+397

No files matched your search

+25
View File
@@ -6,6 +6,9 @@
#include "StreamAPI.h"
#include "Throttle.h"
#include "concurrency/LockGuard.h"
#if defined(MESHTASTIC_LOG_RECORD_MILLIS) && defined(MESHTASTIC_RADIO_TASK)
#include "concurrency/RadioTask.h"
#endif
#include "gps/RTC.h"
#define START1 0x94
@@ -268,11 +271,33 @@ void StreamAPI::emitLogRecord(meshtastic_LogRecord_Level level, const char *src,
fromRadioScratchLog.log_record.time = rtc_sec;
strncpy(fromRadioScratchLog.log_record.source, src, sizeof(fromRadioScratchLog.log_record.source) - 1);
#ifdef MESHTASTIC_LOG_RECORD_MILLIS
char *message = fromRadioScratchLog.log_record.message;
size_t room = sizeof(fromRadioScratchLog.log_record.message) - 1;
// Bench: LogRecord.time is whole seconds, and the host's arrival stamp carries the link's queueing delay.
// Uptime taken here, as the line is logged, lets a node's events be lined up with other nodes' to the ms.
unsigned long stampMs = millis();
#ifdef MESHTASTIC_RADIO_TASK
uint32_t loggedMs;
if (concurrency::loggedAtMs(&loggedMs))
stampMs = loggedMs; // a radio task line the loop is printing now
#endif
const int stamped = snprintf(message, room, "millis=%lu ", stampMs);
if (stamped > 0 && (size_t)stamped < room) {
message += stamped;
room -= stamped;
}
auto num_printed = vsnprintf(message, room, format, arg);
if (num_printed > 0 && (size_t)num_printed <= room &&
message[num_printed - 1] == '\n') // Strip any ending newline, because we have records for framing instead.
message[num_printed - 1] = '\0';
#else
auto num_printed =
vsnprintf(fromRadioScratchLog.log_record.message, sizeof(fromRadioScratchLog.log_record.message) - 1, format, arg);
if (num_printed > 0 && fromRadioScratchLog.log_record.message[num_printed - 1] ==
'\n') // Strip any ending newline, because we have records for framing instead.
fromRadioScratchLog.log_record.message[num_printed - 1] = '\0';
#endif
size_t len =
pb_encode_to_bytes(txBufLog + HEADER_LEN, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratchLog);