1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-29 13:49:21 +08:00

[cpu][darwin] Remove calls to sysctl binary in cpu/cpu_darwin.go #639

Empirical benchmark (calling to cpu.Info):

Lomanics-iMac:~ lomanic$ time ./cpu_info
info 0: {"cpu":0,"vendorId":"GenuineIntel","family":"6","model":"30","stepping":5,"physicalId":"","coreId":"","cores":2,"modelName":"Intel(R) Core(TM) i5-6440HQ CPU @ 2.60GHz","mhz":2590,"cacheSize":256,"flags":["syscall","xd","em64t","lahf","lzcnt","prefetchw","rdtscp","tsci","fpu","vme","de","pse","tsc","msr","pae","mce","cx8","apic","sep","mtrr","pge","mca","cmov","pat","pse36","clfsh","mmx","fxsr","sse","sse2","htt","sse3","ssse3","cx16","sse4.1","sse4.2","popcnt","vmm"],"microcode":""}

real    0m0.049s
user    0m0.023s
sys     0m0.041s
Lomanics-iMac:~ lomanic$ time ./cpu_info.fixed
info 0: {"cpu":0,"vendorId":"GenuineIntel","family":"6","model":"30","stepping":5,"physicalId":"","coreId":"","cores":2,"modelName":"Intel(R) Core(TM) i5-6440HQ CPU @ 2.60GHz","mhz":2590,"cacheSize":256,"flags":["fpu","vme","de","pse","tsc","msr","pae","mce","cx8","apic","sep","mtrr","pge","mca","cmov","pat","pse36","clfsh","mmx","fxsr","sse","sse2","htt","sse3","ssse3","cx16","sse4.1","sse4.2","popcnt","vmm","syscall","xd","em64t","lahf","lzcnt","prefetchw","rdtscp","tsci"],"microcode":""}

real    0m0.010s
user    0m0.004s
sys     0m0.006s
This commit is contained in:
Lomanic 2019-02-22 20:59:16 +01:00
parent 6c6abd6d16
commit 2ec35609d2

View File

@ -4,9 +4,10 @@ package cpu
import ( import (
"context" "context"
"os/exec"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/sys/unix"
) )
// sys/resource.h // sys/resource.h
@ -41,75 +42,46 @@ func Info() ([]InfoStat, error) {
func InfoWithContext(ctx context.Context) ([]InfoStat, error) { func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
var ret []InfoStat var ret []InfoStat
sysctl, err := exec.LookPath("/usr/sbin/sysctl")
if err != nil {
return ret, err
}
out, err := invoke.CommandWithContext(ctx, sysctl, "machdep.cpu")
if err != nil {
return ret, err
}
c := InfoStat{} c := InfoStat{}
for _, line := range strings.Split(string(out), "\n") { c.ModelName, _ = unix.Sysctl("machdep.cpu.brand_string")
values := strings.Fields(line) family, _ := unix.SysctlUint32("machdep.cpu.family")
if len(values) < 1 { c.Family = strconv.FormatUint(uint64(family), 10)
continue model, _ := unix.SysctlUint32("machdep.cpu.model")
} c.Model = strconv.FormatUint(uint64(model), 10)
stepping, _ := unix.SysctlUint32("machdep.cpu.stepping")
t, err := strconv.ParseInt(values[1], 10, 64) c.Stepping = int32(stepping)
// err is not checked here because some value is string. features, err := unix.Sysctl("machdep.cpu.features")
if strings.HasPrefix(line, "machdep.cpu.brand_string") { if err == nil {
c.ModelName = strings.Join(values[1:], " ") for _, v := range strings.Fields(features) {
} else if strings.HasPrefix(line, "machdep.cpu.family") {
c.Family = values[1]
} else if strings.HasPrefix(line, "machdep.cpu.model") {
c.Model = values[1]
} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
if err != nil {
return ret, err
}
c.Stepping = int32(t)
} else if strings.HasPrefix(line, "machdep.cpu.features") {
for _, v := range values[1:] {
c.Flags = append(c.Flags, strings.ToLower(v)) c.Flags = append(c.Flags, strings.ToLower(v))
} }
} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") { }
for _, v := range values[1:] { leaf7Features, err := unix.Sysctl("machdep.cpu.leaf7_features")
if err == nil {
for _, v := range strings.Fields(leaf7Features) {
c.Flags = append(c.Flags, strings.ToLower(v)) c.Flags = append(c.Flags, strings.ToLower(v))
} }
} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") { }
for _, v := range values[1:] { extfeatures, err := unix.Sysctl("machdep.cpu.extfeatures")
if err == nil {
for _, v := range strings.Fields(extfeatures) {
c.Flags = append(c.Flags, strings.ToLower(v)) c.Flags = append(c.Flags, strings.ToLower(v))
} }
} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
if err != nil {
return ret, err
}
c.Cores = int32(t)
} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
if err != nil {
return ret, err
}
c.CacheSize = int32(t)
} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
c.VendorID = values[1]
}
} }
cores, _ := unix.SysctlUint32("machdep.cpu.core_count")
c.Cores = int32(cores)
cacheSize, _ := unix.SysctlUint32("machdep.cpu.cache.size")
c.CacheSize = int32(cacheSize)
c.VendorID, _ = unix.Sysctl("machdep.cpu.vendor")
// Use the rated frequency of the CPU. This is a static value and does not // Use the rated frequency of the CPU. This is a static value and does not
// account for low power or Turbo Boost modes. // account for low power or Turbo Boost modes.
out, err = invoke.CommandWithContext(ctx, sysctl, "hw.cpufrequency") cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency")
if err != nil { if err != nil {
return ret, err return ret, err
} }
c.Mhz = float64(cpuFrequency) / 1000000.0
values := strings.Fields(string(out))
hz, err := strconv.ParseFloat(values[1], 64)
if err != nil {
return ret, err
}
c.Mhz = hz / 1000000.0
return append(ret, c), nil return append(ret, c), nil
} }