|  | @@ -110,6 +110,7 @@ type ServerService struct {
 | 
	
		
			
				|  |  |  	mu                 sync.Mutex
 | 
	
		
			
				|  |  |  	lastCPUTimes       cpu.TimesStat
 | 
	
		
			
				|  |  |  	hasLastCPUSample   bool
 | 
	
		
			
				|  |  | +	hasNativeCPUSample bool
 | 
	
		
			
				|  |  |  	emaCPU             float64
 | 
	
		
			
				|  |  |  	cpuHistory         []CPUSample
 | 
	
		
			
				|  |  |  	cachedCpuSpeedMhz  float64
 | 
	
	
		
			
				|  | @@ -432,23 +433,27 @@ func (s *ServerService) AppendCpuSample(t time.Time, v float64) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (s *ServerService) sampleCPUUtilization() (float64, error) {
 | 
	
		
			
				|  |  | -	// Prefer native Windows API to avoid external deps for CPU percent
 | 
	
		
			
				|  |  | -	if runtime.GOOS == "windows" {
 | 
	
		
			
				|  |  | -		if pct, err := sys.CPUPercentRaw(); err == nil {
 | 
	
		
			
				|  |  | -			s.mu.Lock()
 | 
	
		
			
				|  |  | -			// Smooth with EMA
 | 
	
		
			
				|  |  | -			const alpha = 0.3
 | 
	
		
			
				|  |  | -			if s.emaCPU == 0 {
 | 
	
		
			
				|  |  | -				s.emaCPU = pct
 | 
	
		
			
				|  |  | -			} else {
 | 
	
		
			
				|  |  | -				s.emaCPU = alpha*pct + (1-alpha)*s.emaCPU
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -			val := s.emaCPU
 | 
	
		
			
				|  |  | +	// Try native platform-specific CPU implementation first (Windows, Linux, macOS)
 | 
	
		
			
				|  |  | +	if pct, err := sys.CPUPercentRaw(); err == nil {
 | 
	
		
			
				|  |  | +		s.mu.Lock()
 | 
	
		
			
				|  |  | +		// First call to native method returns 0 (initializes baseline)
 | 
	
		
			
				|  |  | +		if !s.hasNativeCPUSample {
 | 
	
		
			
				|  |  | +			s.hasNativeCPUSample = true
 | 
	
		
			
				|  |  |  			s.mu.Unlock()
 | 
	
		
			
				|  |  | -			return val, nil
 | 
	
		
			
				|  |  | +			return 0, nil
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		// If native call fails, fall back to gopsutil times
 | 
	
		
			
				|  |  | +		// Smooth with EMA
 | 
	
		
			
				|  |  | +		const alpha = 0.3
 | 
	
		
			
				|  |  | +		if s.emaCPU == 0 {
 | 
	
		
			
				|  |  | +			s.emaCPU = pct
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			s.emaCPU = alpha*pct + (1-alpha)*s.emaCPU
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		val := s.emaCPU
 | 
	
		
			
				|  |  | +		s.mu.Unlock()
 | 
	
		
			
				|  |  | +		return val, nil
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	// If native call fails, fall back to gopsutil times
 | 
	
		
			
				|  |  |  	// Read aggregate CPU times (all CPUs combined)
 | 
	
		
			
				|  |  |  	times, err := cpu.Times(false)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
	
		
			
				|  | @@ -471,17 +476,16 @@ func (s *ServerService) sampleCPUUtilization() (float64, error) {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// Compute busy and total deltas
 | 
	
		
			
				|  |  | +	// Note: Guest and GuestNice times are already included in User and Nice respectively,
 | 
	
		
			
				|  |  | +	// so we exclude them to avoid double-counting (Linux kernel accounting)
 | 
	
		
			
				|  |  |  	idleDelta := cur.Idle - s.lastCPUTimes.Idle
 | 
	
		
			
				|  |  | -	// Sum of busy deltas (exclude Idle)
 | 
	
		
			
				|  |  |  	busyDelta := (cur.User - s.lastCPUTimes.User) +
 | 
	
		
			
				|  |  |  		(cur.System - s.lastCPUTimes.System) +
 | 
	
		
			
				|  |  |  		(cur.Nice - s.lastCPUTimes.Nice) +
 | 
	
		
			
				|  |  |  		(cur.Iowait - s.lastCPUTimes.Iowait) +
 | 
	
		
			
				|  |  |  		(cur.Irq - s.lastCPUTimes.Irq) +
 | 
	
		
			
				|  |  |  		(cur.Softirq - s.lastCPUTimes.Softirq) +
 | 
	
		
			
				|  |  | -		(cur.Steal - s.lastCPUTimes.Steal) +
 | 
	
		
			
				|  |  | -		(cur.Guest - s.lastCPUTimes.Guest) +
 | 
	
		
			
				|  |  | -		(cur.GuestNice - s.lastCPUTimes.GuestNice)
 | 
	
		
			
				|  |  | +		(cur.Steal - s.lastCPUTimes.Steal)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	totalDelta := busyDelta + idleDelta
 | 
	
		
			
				|  |  |  
 |