From 72fc497980e2c7f2984ca8a5f98be3c2ffc7fc5f Mon Sep 17 00:00:00 2001 From: "Valentin V. Bartenev" Date: Sun, 10 May 2026 10:02:21 +0300 Subject: [PATCH] Slightly optimize CPU util tracking by branchless tick hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the two separate volatile counters (s_idle_ticks, s_busy_ticks) with a two-element array s_ticks[2]: [0] = idle ticks (xTaskGetCurrentTaskHandle() != s_idle_handle → false → 0) [1] = busy ticks (xTaskGetCurrentTaskHandle() != s_idle_handle → true → 1) The tick hook becomes a single branchless statement: s_ticks[xTaskGetCurrentTaskHandle() != s_idle_handle]++; This eliminates the conditional branch from the tick ISR at the cost of a few additional instructions in IRAM. On Xtensa LX7 the branch is somewhat unpredictable — the system alternates between idle and busy — so removing the misprediction penalty (~5–10 cycles/call) outweighs the slightly larger code size. _onSample() is updated to read s_ticks[0] (idle) and s_ticks[1] (busy) accordingly. All other logic is unchanged. --- arch/esp32/CPUUsageTracker.cpp | 19 +++++++------------ arch/esp32/CPUUsageTracker.h | 3 +-- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/arch/esp32/CPUUsageTracker.cpp b/arch/esp32/CPUUsageTracker.cpp index 8cb7ff61..8a6432f5 100644 --- a/arch/esp32/CPUUsageTracker.cpp +++ b/arch/esp32/CPUUsageTracker.cpp @@ -2,16 +2,11 @@ #include "CPUUsageTracker.h" #include "esp_freertos_hooks.h" -volatile uint32_t CPUUsageTracker::s_idle_ticks = 0; -volatile uint32_t CPUUsageTracker::s_busy_ticks = 0; +volatile uint32_t CPUUsageTracker::s_ticks[2] = {0, 0}; TaskHandle_t CPUUsageTracker::s_idle_handle = nullptr; void IRAM_ATTR CPUUsageTracker::s_tick_hook() { - if (xTaskGetCurrentTaskHandle() == s_idle_handle) { - s_idle_ticks++; - } else { - s_busy_ticks++; - } + s_ticks[xTaskGetCurrentTaskHandle() != s_idle_handle]++; } void CPUUsageTracker::s_sample_cb(void* arg) { @@ -19,14 +14,14 @@ void CPUUsageTracker::s_sample_cb(void* arg) { } void CPUUsageTracker::_onSample() { - const uint32_t busy = s_busy_ticks; - const uint32_t idle = s_idle_ticks; - const uint32_t db = busy - _last_busy; + const uint32_t idle = s_ticks[0]; + const uint32_t busy = s_ticks[1]; const uint32_t di = idle - _last_idle; - _last_busy = busy; + const uint32_t db = busy - _last_busy; _last_idle = idle; + _last_busy = busy; - const uint32_t total = db + di; + const uint32_t total = di + db; const float sample = (total > 0) ? (float)db / (float)total : 0.0f; const uint8_t s8 = (uint8_t)(sample * 255.0f + 0.5f); diff --git a/arch/esp32/CPUUsageTracker.h b/arch/esp32/CPUUsageTracker.h index d951c640..15c7d7d6 100644 --- a/arch/esp32/CPUUsageTracker.h +++ b/arch/esp32/CPUUsageTracker.h @@ -18,8 +18,7 @@ public: private: static constexpr uint8_t SMA_WINDOW = 64; // power of 2 — enables & mask - static volatile uint32_t s_idle_ticks; - static volatile uint32_t s_busy_ticks; + static volatile uint32_t s_ticks[2]; // [0] = idle ticks, [1] = busy ticks static TaskHandle_t s_idle_handle; static void IRAM_ATTR s_tick_hook();