Bladeren bron

Slightly optimize CPU util tracking by branchless tick hook

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.
Valentin V. Bartenev 3 maanden geleden
bovenliggende
commit
72fc497980
2 gewijzigde bestanden met toevoegingen van 8 en 14 verwijderingen
  1. 7 12
      arch/esp32/CPUUsageTracker.cpp
  2. 1 2
      arch/esp32/CPUUsageTracker.h

+ 7 - 12
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);

+ 1 - 2
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();