open-nomad/client/fingerprint/cpu_default_test.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

122 lines
3.6 KiB
Go
Raw Permalink Normal View History

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
//go:build !darwin || !arm64 || !cgo
2015-08-26 21:27:44 +00:00
package fingerprint
import (
"strconv"
2015-08-26 21:27:44 +00:00
"testing"
"github.com/hashicorp/nomad/ci"
2015-08-26 21:27:44 +00:00
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/lib/cgutil"
2018-06-13 22:33:25 +00:00
"github.com/hashicorp/nomad/helper/testlog"
2015-08-26 21:27:44 +00:00
"github.com/hashicorp/nomad/nomad/structs"
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
"github.com/shoenig/test/must"
2015-08-26 21:27:44 +00:00
)
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
func TestCPUFingerprint_Classic(t *testing.T) {
ci.Parallel(t)
logger := testlog.HCLogger(t)
// create cpuset manager so we can ensure cgroup tree is correct
mgr := cgutil.CreateCPUSetManager("", nil, logger)
mgr.Init()
// create the fingerprinter
f := NewCPUFingerprint(logger)
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
node := &structs.Node{Attributes: make(map[string]string)}
request := &FingerprintRequest{Config: &config.Config{}, Node: node}
var response FingerprintResponse
2015-08-26 21:27:44 +00:00
// run the fingerprinter
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
err := f.Fingerprint(request, &response)
must.NoError(t, err)
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
must.True(t, response.Detected)
attributes := response.Attributes
client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips (#16672) * client/fingerprint: correctly fingerprint E/P cores of Apple Silicon chips This PR adds detection of asymetric core types (Power & Efficiency) (P/E) when running on M1/M2 Apple Silicon CPUs. This functionality is provided by shoenig/go-m1cpu which makes use of the Apple IOKit framework to read undocumented registers containing CPU performance data. Currently working on getting that functionality merged upstream into gopsutil, but gopsutil would still not support detecting P vs E cores like this PR does. Also refactors the CPUFingerprinter code to handle the mixed core types, now setting power vs efficiency cpu attributes. For now the scheduler is still unaware of mixed core types - on Apple platforms tasks cannot reserve cores anyway so it doesn't matter, but at least now the total CPU shares available will be correct. Future work should include adding support for detecting P/E cores on the latest and upcoming Intel chips, where computation of total cpu shares is currently incorrect. For that, we should also include updating the scheduler to be core-type aware, so that tasks of resources.cores on Linux platforms can be assigned the correct number of CPU shares for the core type(s) they have been assigned. node attributes before cpu.arch = arm64 cpu.modelname = Apple M2 Pro cpu.numcores = 12 cpu.reservablecores = 0 cpu.totalcompute = 1000 node attributes after cpu.arch = arm64 cpu.frequency.efficiency = 2424 cpu.frequency.power = 3504 cpu.modelname = Apple M2 Pro cpu.numcores.efficiency = 4 cpu.numcores.power = 8 cpu.reservablecores = 0 cpu.totalcompute = 37728 * fingerprint/cpu: follow up cr items
2023-03-28 13:27:58 +00:00
must.NotNil(t, attributes)
must.MapContainsKey(t, attributes, "cpu.numcores")
must.MapContainsKey(t, attributes, "cpu.modelname")
must.MapContainsKey(t, attributes, "cpu.frequency")
must.MapContainsKey(t, attributes, "cpu.totalcompute")
must.Positive(t, response.Resources.CPU)
must.Positive(t, response.NodeResources.Cpu.CpuShares)
must.Positive(t, response.NodeResources.Cpu.SharesPerCore())
must.SliceNotEmpty(t, response.NodeResources.Cpu.ReservableCpuCores)
// asymetric core detection currently only works with apple silicon
must.MapNotContainsKey(t, attributes, "cpu.numcores.power")
must.MapNotContainsKey(t, attributes, "cpu.numcores.efficiency")
2015-08-26 21:27:44 +00:00
}
2017-06-27 18:56:52 +00:00
// TestCPUFingerprint_OverrideCompute asserts that setting cpu_total_compute in
// the client config overrides the detected CPU freq (if any).
func TestCPUFingerprint_OverrideCompute(t *testing.T) {
ci.Parallel(t)
f := NewCPUFingerprint(testlog.HCLogger(t))
2017-06-27 18:56:52 +00:00
node := &structs.Node{
Attributes: make(map[string]string),
}
cfg := &config.Config{
ReservableCores: []uint16{0, 1, 2},
}
var originalCPU int
2017-06-27 18:56:52 +00:00
{
request := &FingerprintRequest{Config: cfg, Node: node}
var response FingerprintResponse
err := f.Fingerprint(request, &response)
if err != nil {
t.Fatalf("err: %v", err)
}
2018-01-31 22:03:55 +00:00
if !response.Detected {
t.Fatalf("expected response to be applicable")
}
if attr := response.Attributes["cpu.reservablecores"]; attr != "3" {
t.Fatalf("expected cpu.reservablecores == 3 but found %s", attr)
}
if response.Resources.CPU == 0 {
t.Fatalf("expected fingerprint of cpu of but found 0")
}
2017-06-27 18:56:52 +00:00
originalCPU = response.Resources.CPU
2017-06-27 18:56:52 +00:00
}
{
// Override it with a setting
cfg.CpuCompute = originalCPU + 123
// Make sure the Fingerprinter applies the override to the node resources
request := &FingerprintRequest{Config: cfg, Node: node}
var response FingerprintResponse
err := f.Fingerprint(request, &response)
if err != nil {
t.Fatalf("err: %v", err)
}
2018-09-30 00:23:41 +00:00
// COMPAT(0.10): Remove in 0.10
if response.Resources.CPU != cfg.CpuCompute {
t.Fatalf("expected override cpu of %d but found %d", cfg.CpuCompute, response.Resources.CPU)
}
2018-10-16 22:34:32 +00:00
if response.NodeResources.Cpu.CpuShares != int64(cfg.CpuCompute) {
2018-10-04 21:33:09 +00:00
t.Fatalf("expected override cpu of %d but found %d", cfg.CpuCompute, response.NodeResources.Cpu.CpuShares)
2018-09-30 00:23:41 +00:00
}
if response.Attributes["cpu.totalcompute"] != strconv.Itoa(cfg.CpuCompute) {
t.Fatalf("expected override cpu.totalcompute of %d but found %s", cfg.CpuCompute, response.Attributes["cpu.totalcompute"])
}
if attr := response.Attributes["cpu.reservablecores"]; attr != "3" {
t.Fatalf("expected cpu.reservablecores == 3 but found %s", attr)
}
2017-06-27 18:56:52 +00:00
}
}