git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/sysinfo/cpu.go (about) 1 // Copyright © 2016 Zlatko Čalušić 2 // 3 // Use of this source code is governed by an MIT-style license that can be found in the LICENSE file. 4 5 package sysinfo 6 7 import ( 8 "bufio" 9 "fmt" 10 "os" 11 "regexp" 12 "runtime" 13 "strconv" 14 "strings" 15 ) 16 17 // CPU information. 18 type CPU struct { 19 Vendor string `json:"vendor,omitempty"` 20 Model string `json:"model,omitempty"` 21 Speed uint `json:"speed,omitempty"` // CPU clock rate in MHz 22 Cache uint `json:"cache,omitempty"` // CPU cache size in KB 23 Cpus uint `json:"cpus,omitempty"` // number of physical CPUs 24 Cores uint `json:"cores,omitempty"` // number of physical CPU cores 25 Threads uint `json:"threads,omitempty"` // number of logical (HT) CPU cores 26 } 27 28 var ( 29 reTwoColumns = regexp.MustCompile("\t+: ") 30 reExtraSpace = regexp.MustCompile(" +") 31 reCacheSize = regexp.MustCompile(`^(\d+) KB$`) 32 ) 33 34 func (si *SysInfo) getCPUInfo() { 35 si.CPU.Threads = uint(runtime.NumCPU()) 36 37 f, err := os.Open("/proc/cpuinfo") 38 if err != nil { 39 return 40 } 41 defer f.Close() 42 43 cpu := make(map[string]bool) 44 core := make(map[string]bool) 45 46 var cpuID string 47 48 s := bufio.NewScanner(f) 49 for s.Scan() { 50 if sl := reTwoColumns.Split(s.Text(), 2); sl != nil { 51 switch sl[0] { 52 case "physical id": 53 cpuID = sl[1] 54 cpu[cpuID] = true 55 case "core id": 56 coreID := fmt.Sprintf("%s/%s", cpuID, sl[1]) 57 core[coreID] = true 58 case "vendor_id": 59 if si.CPU.Vendor == "" { 60 si.CPU.Vendor = sl[1] 61 } 62 case "model name": 63 if si.CPU.Model == "" { 64 // CPU model, as reported by /proc/cpuinfo, can be a bit ugly. Clean up... 65 model := reExtraSpace.ReplaceAllLiteralString(sl[1], " ") 66 si.CPU.Model = strings.Replace(model, "- ", "-", 1) 67 } 68 case "cache size": 69 if si.CPU.Cache == 0 { 70 if m := reCacheSize.FindStringSubmatch(sl[1]); m != nil { 71 if cache, err := strconv.ParseUint(m[1], 10, 64); err == nil { 72 si.CPU.Cache = uint(cache) 73 } 74 } 75 } 76 } 77 } 78 } 79 if s.Err() != nil { 80 return 81 } 82 83 // getNodeInfo() must have run first, to detect if we're dealing with a virtualized CPU! Detecting number of 84 // physical processors and/or cores is totally unreliable in virtualized environments, so let's not do it. 85 if si.Node.Hostname == "" || si.Node.Hypervisor != "" { 86 return 87 } 88 89 si.CPU.Cpus = uint(len(cpu)) 90 si.CPU.Cores = uint(len(core)) 91 }