Supports all linux operating systems. currently tested on x86, mips64le and loong64.
Example output:
$ go test -bench=.*
goos: linux
goarch: loong64
pkg: runtime
cpu: Loongson-3A5000-HV @ 2500.00MHz
BenchmarkSemTable/OneAddrCollision/n=1000 19261 62302 ns/op
...
Change-Id: I02db12d70c11327e4625bb6e59f30dfaf37c2db0
Reviewed-on: https://go-review.googlesource.com/c/go/+/508735
Reviewed-by: Meidan Li <limeidan@loongson.cn>
Reviewed-by: Russ Cox <rsc@golang.org>
TryBot-Bypass: Russ Cox <rsc@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Russ Cox <rsc@golang.org>
func main() {
fmt.Printf("# GOARCH: %s\n", runtime.GOARCH)
- fmt.Printf("# CPU: %s\n", sysinfo.CPU.Name())
+ fmt.Printf("# CPU: %s\n", sysinfo.CPUName())
fmt.Printf("# GOOS: %s\n", runtime.GOOS)
ver, err := osinfo.Version()
< net/rpc/jsonrpc;
# System Information
- internal/cpu, sync
+ bufio, bytes, internal/cpu, io, os, strings, sync
< internal/sysinfo;
# Test-only
--- /dev/null
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sysinfo
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+ "os"
+ "strings"
+)
+
+func readLinuxProcCPUInfo(buf []byte) error {
+ f, err := os.Open("/proc/cpuinfo")
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ _, err = io.ReadFull(f, buf)
+ if err != nil && err != io.ErrUnexpectedEOF {
+ return err
+ }
+
+ return nil
+}
+
+func osCpuInfoName() string {
+ modelName := ""
+ cpuMHz := ""
+
+ // The 512-byte buffer is enough to hold the contents of CPU0
+ buf := make([]byte, 512)
+ err := readLinuxProcCPUInfo(buf)
+ if err != nil {
+ return ""
+ }
+
+ scanner := bufio.NewScanner(bytes.NewReader(buf))
+ for scanner.Scan() {
+ line := scanner.Text()
+ if !strings.Contains(line, ":") {
+ continue
+ }
+
+ field := strings.SplitN(line, ": ", 2)
+ switch strings.TrimSpace(field[0]) {
+ case "Model Name", "model name":
+ modelName = field[1]
+ case "CPU MHz", "cpu MHz":
+ cpuMHz = field[1]
+ }
+ }
+
+ if modelName == "" {
+ return ""
+ }
+
+ if cpuMHz == "" {
+ return modelName
+ }
+
+ // The modelName field already contains the frequency information,
+ // so the cpuMHz field information is not needed.
+ // modelName filed example:
+ // Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
+ f := [...]string{"GHz", "MHz"}
+ for _, v := range f {
+ if strings.Contains(modelName, v) {
+ return modelName
+ }
+ }
+
+ return modelName + " @ " + cpuMHz + "MHz"
+}
--- /dev/null
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !linux
+
+package sysinfo
+
+func osCpuInfoName() string {
+ return ""
+}
package sysinfo
import (
- internalcpu "internal/cpu"
+ "internal/cpu"
"sync"
)
-type cpuInfo struct {
+var cpuInfo struct {
once sync.Once
name string
}
-var CPU cpuInfo
-
-func (cpu *cpuInfo) Name() string {
- cpu.once.Do(func() {
+func CPUName() string {
+ cpuInfo.once.Do(func() {
// Try to get the information from internal/cpu.
- if name := internalcpu.Name(); name != "" {
- cpu.name = name
+ if name := cpu.Name(); name != "" {
+ cpuInfo.name = name
return
}
+
// TODO(martisch): use /proc/cpuinfo and /sys/devices/system/cpu/ on Linux as fallback.
+ if name := osCpuInfoName(); name != "" {
+ cpuInfo.name = name
+ return
+ }
})
- return cpu.name
+
+ return cpuInfo.name
}
if b.importPath != "" {
fmt.Fprintf(b.w, "pkg: %s\n", b.importPath)
}
- if cpu := sysinfo.CPU.Name(); cpu != "" {
+ if cpu := sysinfo.CPUName(); cpu != "" {
fmt.Fprintf(b.w, "cpu: %s\n", cpu)
}
})
if b.importPath != "" {
fmt.Printf("pkg: %s\n", b.importPath)
}
- if cpu := sysinfo.CPU.Name(); cpu != "" {
+ if cpu := sysinfo.CPUName(); cpu != "" {
fmt.Printf("cpu: %s\n", cpu)
}
})