Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormhsanaei <ho3ein.sanaei@gmail.com>2025-09-16 15:15:18 +0300
committermhsanaei <ho3ein.sanaei@gmail.com>2025-09-16 15:15:18 +0300
commitecfffa882a159bb2a12954eed0f68eb4ec1a6120 (patch)
tree18b34d40f61fa6b4103fd663e6c7b1f8a614a487 /util/sys/sys_linux.go
parent3af5026abe639e9cb5a9f695c02624ac6e173077 (diff)
CPU History, CPU Utilization
Diffstat (limited to 'util/sys/sys_linux.go')
-rw-r--r--util/sys/sys_linux.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/util/sys/sys_linux.go b/util/sys/sys_linux.go
index d4e6e8ae..8a494d62 100644
--- a/util/sys/sys_linux.go
+++ b/util/sys/sys_linux.go
@@ -4,10 +4,14 @@
package sys
import (
+ "bufio"
"bytes"
"fmt"
"io"
"os"
+ "strconv"
+ "strings"
+ "sync"
)
func getLinesNum(filename string) (int, error) {
@@ -79,3 +83,99 @@ func safeGetLinesNum(path string) (int, error) {
}
return getLinesNum(path)
}
+
+// --- CPU Utilization (Linux native) ---
+
+var (
+ cpuMu sync.Mutex
+ lastTotal uint64
+ lastIdleAll uint64
+ hasLast bool
+)
+
+// CPUPercentRaw returns instantaneous total CPU utilization by reading /proc/stat.
+// First call initializes and returns 0; subsequent calls return busy/total * 100.
+func CPUPercentRaw() (float64, error) {
+ f, err := os.Open("/proc/stat")
+ if err != nil {
+ return 0, err
+ }
+ defer f.Close()
+
+ rd := bufio.NewReader(f)
+ line, err := rd.ReadString('\n')
+ if err != nil && err != io.EOF {
+ return 0, err
+ }
+ // Expect line like: cpu user nice system idle iowait irq softirq steal guest guest_nice
+ fields := strings.Fields(line)
+ if len(fields) < 5 || fields[0] != "cpu" {
+ return 0, fmt.Errorf("unexpected /proc/stat format")
+ }
+
+ var nums []uint64
+ for i := 1; i < len(fields); i++ {
+ v, err := strconv.ParseUint(fields[i], 10, 64)
+ if err != nil {
+ break
+ }
+ nums = append(nums, v)
+ }
+ if len(nums) < 4 { // need at least user,nice,system,idle
+ return 0, fmt.Errorf("insufficient cpu fields")
+ }
+
+ // Conform with standard Linux CPU accounting
+ var user, nice, system, idle, iowait, irq, softirq, steal uint64
+ user = nums[0]
+ if len(nums) > 1 {
+ nice = nums[1]
+ }
+ if len(nums) > 2 {
+ system = nums[2]
+ }
+ if len(nums) > 3 {
+ idle = nums[3]
+ }
+ if len(nums) > 4 {
+ iowait = nums[4]
+ }
+ if len(nums) > 5 {
+ irq = nums[5]
+ }
+ if len(nums) > 6 {
+ softirq = nums[6]
+ }
+ if len(nums) > 7 {
+ steal = nums[7]
+ }
+
+ idleAll := idle + iowait
+ nonIdle := user + nice + system + irq + softirq + steal
+ total := idleAll + nonIdle
+
+ cpuMu.Lock()
+ defer cpuMu.Unlock()
+
+ if !hasLast {
+ lastTotal = total
+ lastIdleAll = idleAll
+ hasLast = true
+ return 0, nil
+ }
+
+ totald := total - lastTotal
+ idled := idleAll - lastIdleAll
+ lastTotal = total
+ lastIdleAll = idleAll
+
+ if totald == 0 {
+ return 0, nil
+ }
+ busy := totald - idled
+ pct := float64(busy) / float64(totald) * 100.0
+ if pct > 100 {
+ pct = 100
+ }
+ return pct, nil
+}