/ src / utils / cpu-monitor.js
cpu-monitor.js
 1  /**
 2   * Real-time CPU usage monitor
 3   * Samples os.cpus() tick counts every 200ms for instantaneous CPU utilization.
 4   * Much more responsive than os.loadavg() which has a 30-60s exponential lag.
 5   */
 6  
 7  import { cpus } from 'os';
 8  
 9  const SAMPLE_INTERVAL_MS = 200;
10  
11  let currentCpuUsage = 0; // 0.0 to 1.0 normalized across all cores
12  let monitorInterval = null;
13  let lastSnapshot = null;
14  
15  function takeCpuSnapshot() {
16    return cpus().map(cpu => ({ ...cpu.times }));
17  }
18  
19  function computeUsage(before, after) {
20    let totalBusy = 0;
21    let totalTicks = 0;
22  
23    for (let i = 0; i < before.length; i++) {
24      const b = before[i];
25      const a = after[i];
26      const idle = a.idle - b.idle;
27      const total = a.user - b.user + (a.nice - b.nice) + (a.sys - b.sys) + (a.irq - b.irq) + idle;
28      if (total > 0) {
29        totalBusy += total - idle;
30        totalTicks += total;
31      }
32    }
33  
34    return totalTicks > 0 ? totalBusy / totalTicks : 0;
35  }
36  
37  function startMonitor() {
38    if (monitorInterval) return;
39    lastSnapshot = takeCpuSnapshot();
40  
41    monitorInterval = setInterval(() => {
42      const now = takeCpuSnapshot();
43      currentCpuUsage = computeUsage(lastSnapshot, now);
44      lastSnapshot = now;
45    }, SAMPLE_INTERVAL_MS);
46  
47    // Don't prevent process exit
48    if (monitorInterval.unref) monitorInterval.unref();
49  }
50  
51  export function getCurrentCpuUsage() {
52    if (!monitorInterval) startMonitor();
53    return currentCpuUsage;
54  }
55  
56  export function stopCpuMonitor() {
57    if (monitorInterval) {
58      clearInterval(monitorInterval);
59      monitorInterval = null;
60    }
61  }
62  
63  // Auto-start on import
64  startMonitor();