diff options
Diffstat (limited to 'util/sys/sys_darwin.go')
| -rw-r--r-- | util/sys/sys_darwin.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/util/sys/sys_darwin.go b/util/sys/sys_darwin.go index 3f5b2072..6ecc78c0 100644 --- a/util/sys/sys_darwin.go +++ b/util/sys/sys_darwin.go @@ -4,7 +4,12 @@ package sys import ( + "encoding/binary" + "fmt" + "sync" + "github.com/shirou/gopsutil/v4/net" + "golang.org/x/sys/unix" ) func GetTCPCount() (int, error) { @@ -22,3 +27,69 @@ func GetUDPCount() (int, error) { } return len(stats), nil } + +// --- CPU Utilization (macOS native) --- + +// sysctl kern.cp_time returns an array of 5 longs: user, nice, sys, idle, intr. +// We compute utilization deltas without cgo. +var ( + cpuMu sync.Mutex + lastTotals [5]uint64 + hasLastCPUT bool +) + +func CPUPercentRaw() (float64, error) { + raw, err := unix.SysctlRaw("kern.cp_time") + if err != nil { + return 0, err + } + // Expect either 5*8 bytes (uint64) or 5*4 bytes (uint32) + var out [5]uint64 + switch len(raw) { + case 5 * 8: + for i := 0; i < 5; i++ { + out[i] = binary.LittleEndian.Uint64(raw[i*8 : (i+1)*8]) + } + case 5 * 4: + for i := 0; i < 5; i++ { + out[i] = uint64(binary.LittleEndian.Uint32(raw[i*4 : (i+1)*4])) + } + default: + return 0, fmt.Errorf("unexpected kern.cp_time size: %d", len(raw)) + } + + // user, nice, sys, idle, intr + user := out[0] + nice := out[1] + sysv := out[2] + idle := out[3] + intr := out[4] + + cpuMu.Lock() + defer cpuMu.Unlock() + + if !hasLastCPUT { + lastTotals = out + hasLastCPUT = true + return 0, nil + } + + dUser := user - lastTotals[0] + dNice := nice - lastTotals[1] + dSys := sysv - lastTotals[2] + dIdle := idle - lastTotals[3] + dIntr := intr - lastTotals[4] + + lastTotals = out + + totald := dUser + dNice + dSys + dIdle + dIntr + if totald == 0 { + return 0, nil + } + busy := totald - dIdle + pct := float64(busy) / float64(totald) * 100.0 + if pct > 100 { + pct = 100 + } + return pct, nil +} |
