Skip to content

Commit

Permalink
cpu: add frequency support for apple silicon m1/m2 cpus
Browse files Browse the repository at this point in the history
This PR adds support for reading the frequency of Apple Silicon
M1/M2 CPUs. We do so by reading the values out of the IOKit
framework, as a few other projects have now demonstrated to be
possible. This requires the use of CGO. The library provides a
convenience IsAppleSilicon() guard to detect whether the values
can be read.

Currently gopsutil does not support the big.LITTLE CPU architectures
(i think?) - in fact the P and E cores have different max frequencies.
For now, just read the P core frequency. The E core data is readily
available if we want to read it in the future.

Closes shirou#1000

Small example program

```go
package main

import (
        "fmt"

        "github.com/shoenig/go-m1cpu"

        "github.com/shirou/gopsutil/v3/cpu"
)

func main() {
        fmt.Println("is Apple Silicon:", m1cpu.IsAppleSilicon())
        fmt.Println("model name", m1cpu.ModelName())
        fmt.Println("pCore GHz", m1cpu.PCoreGHz())
        fmt.Println("eCore GHz", m1cpu.ECoreGHz())
        fmt.Println("pCore Hz", m1cpu.PCoreHz())
        fmt.Println("eCore Hz", m1cpu.ECoreHz())

        fmt.Println("----- gopsutil ----")

        infos, err := cpu.Info()
        if err != nil {
                panic(err)
        }

        for _, info := range infos {
                fmt.Println("info.Mhz", info.Mhz)
        }
}
```

```shell
go run main.go
is Apple Silicon: true
model name Apple M2 Pro
pCore GHz 3.504
eCore GHz 2.424
pCore Hz 3504000000
eCore Hz 2424000000
----- gopsutil ----
info.Mhz 3.504e+09
```
  • Loading branch information
shoenig committed Mar 28, 2023
1 parent c036597 commit 8617ff6
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
15 changes: 10 additions & 5 deletions cpu/cpu_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"strings"

"github.com/shoenig/go-m1cpu"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -85,11 +86,15 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
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
// account for low power or Turbo Boost modes.
cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency")
if err == nil {
c.Mhz = float64(cpuFrequency) / 1000000.0
if m1cpu.IsAppleSilicon() {
c.Mhz = float64(m1cpu.PCoreHz() / 1_000_000)
} else {
// Use the rated frequency of the CPU. This is a static value and does not
// account for low power or Turbo Boost modes.
cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency")
if err == nil {
c.Mhz = float64(cpuFrequency) / 1000000.0
}
}

return append(ret, c), nil
Expand Down
33 changes: 33 additions & 0 deletions cpu/cpu_darwin_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//go:build darwin
// +build darwin

package cpu

import (
"testing"

"github.com/shoenig/go-m1cpu"
)

func Test_CpuInfo_AppleSilicon(t *testing.T) {
if !m1cpu.IsAppleSilicon() {
t.Skip("wrong cpu type")
}

v, err := Info()
if err != nil {
t.Errorf("cpu info should be implemented on darwin systems")
}

for _, vv := range v {
if vv.ModelName == "" {
t.Errorf("could not get CPU info: %v", vv)
}
if vv.Mhz <= 0 {
t.Errorf("could not get frequency of: %s", vv.ModelName)
}
if vv.Mhz > 6000 {
t.Errorf("cpu frequency is absurdly high value: %f MHz", vv.Mhz)
}
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/google/go-cmp v0.5.9
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c
github.com/shoenig/go-m1cpu v0.1.4
github.com/stretchr/testify v1.8.2
github.com/tklauser/go-sysconf v0.3.11
github.com/yusufpapurcu/wmi v1.2.2
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVbozs=
github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down

0 comments on commit 8617ff6

Please sign in to comment.