perf(memory): reduce internal RAM pressure across network services

- allocate remote log queues and upload buffers from PSRAM
- move mbedTLS and NimBLE dynamic allocations to external memory
- right-size Wi-Fi state, task monitor, and audio worker stacks
- limit retained remote log files to 12
This commit is contained in:
chenjintao
2026-08-14 10:08:54 +08:00
parent 841fe32c49
commit c56c65462e
3 changed files with 80 additions and 17 deletions
@@ -98,7 +98,7 @@ typedef struct {
char text[CONFIG_TQ_REMOTE_LOG_ENTRY_MAX_BYTES];
} remote_log_entry_t;
static remote_log_entry_t s_queue[CONFIG_TQ_REMOTE_LOG_QUEUE_LEN];
static remote_log_entry_t *s_queue;
static size_t s_queue_read;
static size_t s_queue_count;
static uint32_t s_dropped_count;
@@ -119,6 +119,50 @@ static bool s_coredump_reported;
static size_t s_coredump_addr;
static size_t s_coredump_size;
static void *remote_log_psram_calloc(size_t count, size_t size)
{
if (count == 0U || size == 0U) {
return NULL;
}
return heap_caps_calloc(count, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
static void *remote_log_psram_malloc(size_t size)
{
if (size == 0U) {
return NULL;
}
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
static bool allocate_queue(void)
{
if (s_queue != NULL) {
return true;
}
s_queue = (remote_log_entry_t *)remote_log_psram_calloc(
CONFIG_TQ_REMOTE_LOG_QUEUE_LEN,
sizeof(*s_queue));
if (s_queue != NULL) {
s_queue_read = 0U;
s_queue_count = 0U;
}
return s_queue != NULL;
}
static void release_queue(void)
{
if (s_queue == NULL) {
return;
}
heap_caps_free(s_queue);
s_queue = NULL;
s_queue_read = 0U;
s_queue_count = 0U;
}
static bool remote_log_path_active(void)
{
return xTaskGetCurrentTaskHandle() == s_remote_log_task;
@@ -165,7 +209,7 @@ static bool should_capture_level(char level)
static void enqueue_line(const char *line, bool truncated)
{
if (line == NULL || line[0] == '\0') {
if (line == NULL || line[0] == '\0' || s_queue == NULL) {
return;
}
@@ -228,7 +272,7 @@ static int remote_log_vprintf(const char *fmt, va_list args)
static bool dequeue_entry(remote_log_entry_t *out_entry)
{
if (out_entry == NULL) {
if (out_entry == NULL || s_queue == NULL) {
return false;
}
@@ -760,8 +804,8 @@ static esp_err_t build_upload_body(uint32_t sequence,
static bool upload_one_file(uint32_t sequence)
{
uint32_t dropped = snapshot_and_clear_dropped_count();
char *body = (char *)malloc(REMOTE_LOG_UPLOAD_BODY_MAX);
char *response = (char *)malloc(REMOTE_LOG_RESPONSE_MAX);
char *body = (char *)remote_log_psram_malloc(REMOTE_LOG_UPLOAD_BODY_MAX);
char *response = (char *)remote_log_psram_malloc(REMOTE_LOG_RESPONSE_MAX);
if (body == NULL || response == NULL) {
free(body);
free(response);
@@ -924,8 +968,8 @@ static bool upload_coredump_report(void)
return false;
}
char *body = (char *)malloc(2048);
char *response = (char *)malloc(REMOTE_LOG_RESPONSE_MAX);
char *body = (char *)remote_log_psram_malloc(2048);
char *response = (char *)remote_log_psram_malloc(REMOTE_LOG_RESPONSE_MAX);
if (body == NULL || response == NULL) {
free(body);
free(response);
@@ -971,11 +1015,12 @@ static bool upload_coredump_report(void)
static void log_startup_self_check(void)
{
ESP_LOGW("remote_log",
"enabled endpoint=%s dir=%s pending_files=%u queue=%u max_files=%u file_max=%u coredump_present=%d coredump_size=%u",
"enabled endpoint=%s dir=%s pending_files=%u queue=%u queue_bytes=%u storage=PSRAM max_files=%u file_max=%u coredump_present=%d coredump_size=%u",
CONFIG_TQ_REMOTE_LOG_ENDPOINT,
REMOTE_LOG_DIR,
(unsigned)count_pending_files(),
(unsigned)CONFIG_TQ_REMOTE_LOG_QUEUE_LEN,
(unsigned)(CONFIG_TQ_REMOTE_LOG_QUEUE_LEN * sizeof(*s_queue)),
(unsigned)CONFIG_TQ_REMOTE_LOG_MAX_FILES,
(unsigned)CONFIG_TQ_REMOTE_LOG_FILE_MAX_BYTES,
s_coredump_present,
@@ -1007,6 +1052,7 @@ static void remote_log_task(void *arg)
esp_err_t mount_err = domain_runtime_mount_logfs();
if (mount_err != ESP_OK) {
release_queue();
s_remote_log_task = NULL;
vTaskDelete(NULL);
return;
@@ -1062,6 +1108,14 @@ esp_err_t control_plane_remote_log_start(void)
return ESP_OK;
}
if (!allocate_queue()) {
ESP_LOGE("remote_log",
"PSRAM queue allocation failed: entries=%u entry_bytes=%u",
(unsigned)CONFIG_TQ_REMOTE_LOG_QUEUE_LEN,
(unsigned)sizeof(*s_queue));
return ESP_ERR_NO_MEM;
}
s_stop_requested = false;
BaseType_t created = xTaskCreatePinnedToCore(remote_log_task,
"cp_remote_log",
@@ -1071,7 +1125,11 @@ esp_err_t control_plane_remote_log_start(void)
&s_remote_log_task,
CONFIG_TQ_NETWORK_TASK_CORE < 0 ? tskNO_AFFINITY :
(BaseType_t)CONFIG_TQ_NETWORK_TASK_CORE);
return created == pdPASS ? ESP_OK : ESP_ERR_NO_MEM;
if (created != pdPASS) {
release_queue();
return ESP_ERR_NO_MEM;
}
return ESP_OK;
}
esp_err_t control_plane_remote_log_flush_now(void)
@@ -1152,6 +1210,7 @@ esp_err_t control_plane_remote_log_format_status(char *out, size_t out_len)
void control_plane_remote_log_stop(int timeout_ms)
{
if (s_remote_log_task == NULL) {
release_queue();
return;
}
@@ -1167,6 +1226,7 @@ void control_plane_remote_log_stop(int timeout_ms)
vTaskDelete(s_remote_log_task);
s_remote_log_task = NULL;
}
release_queue();
}
#else
esp_err_t control_plane_remote_log_start(void)
@@ -22,8 +22,8 @@
#define CONTROL_PLANE_MODEL_CMD_TASK_STACK_SIZE (1024 * 4)
#define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE (1024 * 12)
#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 12)
#define CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE (1024 * 6)
#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 10)
#define CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE (1024 * 4)
#define CONTROL_PLANE_REMOTE_LOG_STOP_WAIT_MS 1500
#define CONTROL_PLANE_MODEL_CMD_QUEUE_LEN 4
#define CONTROL_PLANE_MODEL_CMD_RECV_TIMEOUT_MS 200
+9 -6
View File
@@ -12,6 +12,9 @@ CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=6144
CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y
# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL is not set
# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE=y
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_CONNECT_TIMEOUT_MS=30000
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES=2
@@ -56,7 +59,7 @@ CONFIG_TQ_REMOTE_LOG_ENTRY_MAX_BYTES=256
CONFIG_TQ_REMOTE_LOG_BATCH_MAX_ENTRIES=30
CONFIG_TQ_REMOTE_LOG_FLUSH_INTERVAL_MS=5000
CONFIG_TQ_REMOTE_LOG_UPLOAD_TIMEOUT_MS=8000
CONFIG_TQ_REMOTE_LOG_MAX_FILES=24
CONFIG_TQ_REMOTE_LOG_MAX_FILES=12
CONFIG_TQ_REMOTE_LOG_FILE_MAX_BYTES=16384
CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y
# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set
@@ -186,14 +189,14 @@ CONFIG_MULTIMODAL_AUDIO_I2S_WS_GPIO=41
CONFIG_MULTIMODAL_AUDIO_I2S_DOUT_GPIO=40
CONFIG_MULTIMODAL_AUDIO_I2S_DIN_GPIO=42
CONFIG_MULTIMODAL_AUDIO_UPLINK_TASK_STACK=32768
CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_TASK_STACK=12288
CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_TASK_STACK=8192
CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_QUEUE_LEN=24
CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_TIMEOUT_MS=5
CONFIG_MULTIMODAL_AUDIO_CODEC_CHANNELS=2
CONFIG_MULTIMODAL_AUDIO_AEC_REFERENCE_CHANNEL=1
CONFIG_MULTIMODAL_AUDIO_AEC_FILTER_LENGTH=4
CONFIG_MULTIMODAL_AUDIO_UPLINK_MAX_PACKET_BYTES=1024
CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_PLAYBACK_TASK_STACK=12288
CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_PLAYBACK_TASK_STACK=10240
# CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_DIAGNOSTICS_ENABLE is not set
CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_ACTIVE_STALL_MUTE_MS=3000
CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_PREBUFFER_MS=160
@@ -232,10 +235,10 @@ CONFIG_MULTIMODAL_RECONNECT_DELAY_MS=2000
CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK=y
CONFIG_ESP_WS_CLIENT_TX_LOCK_TIMEOUT_MS=2000
# mbedTLS certificate parsing and dynamic record buffers otherwise compete for
# internal DRAM with LCD/audio/network startup. Use the default allocator so
# ordinary TLS heap can spill to PSRAM when the internal heap is fragmented.
# internal DRAM with LCD/audio/network startup. Allocate TLS heap from PSRAM.
# CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set
CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC=y
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
# TLS renegotiation is not used by the device's HTTPS/WSS clients. With dynamic
# TLS buffers and concurrent WebSocket RX/TX, its write-side counter check can