123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- // Copyright © 2021 Jeffrey H. Johnson <trnsz@pobox.com>
- // Copyright © 2021 Gridfinity, LLC.
- // Copyright © 2019 Neal.
- // Copyright © 2018 lrita@163.com.
- //
- // Use of this source code is governed by the MIT
- // license that can be found in the LICENSE file.
- package gonuma_test
- import (
- "runtime"
- "sync"
- "syscall"
- "testing"
- _ "unsafe"
- gonuma "github.com/johnsonjh/gonuma"
- "github.com/stretchr/testify/require"
- )
- func TestNotNUMAavailable(t *testing.T) {
- if gonuma.NUMAavailable() {
- t.Skip("TestNotNUMAavailable")
- }
- assert := require.New(t)
- _, err := gonuma.GetMemPolicy(nil, nil, 0)
- assert.Equal(syscall.ENOSYS, err)
- assert.Equal(
- syscall.ENOSYS,
- gonuma.SetMemPolicy(gonuma.MPolDefault, nil),
- )
- assert.Equal(syscall.ENOSYS, gonuma.Bind(nil))
- assert.Equal(syscall.ENOSYS, gonuma.MBind(nil, 0, 0, 0, nil))
- _, err = gonuma.GetSchedAffinity(0, nil)
- assert.Equal(syscall.ENOSYS, err)
- assert.Equal(syscall.ENOSYS, gonuma.SetSchedAffinity(0, nil))
- assert.Equal(syscall.ENOSYS, gonuma.RunOnNode(-1))
- assert.Equal(syscall.ENOSYS, gonuma.RunOnNode(0))
- assert.Error(gonuma.RunOnNode(gonuma.NodePossibleCount() + 1))
- assert.Error(gonuma.RunOnNode(-2))
- for i := 0; i < gonuma.CPUCount()+10; i++ {
- node, err := gonuma.CPUToNode(i)
- if i < gonuma.CPUCount() {
- assert.NoError(err)
- assert.Equal(0, node)
- } else {
- assert.Error(err)
- }
- }
- _, err = gonuma.NodeToCPUMask(gonuma.NodePossibleCount() + 1)
- assert.Error(err)
- _, err = gonuma.NodeToCPUMask(gonuma.NodePossibleCount() + 1)
- assert.Error(err)
- _, err = gonuma.RunningNodesMask()
- assert.Error(err)
- _, err = gonuma.RunningCPUMask()
- assert.Error(err)
- assert.Equal(syscall.ENOSYS, gonuma.RunOnNodeMask(gonuma.NodeMask()))
- }
- func TestNodeMemSize64(t *testing.T) {
- var (
- assert = require.New(t)
- nodemask = gonuma.NodeMask()
- )
- if !gonuma.NUMAavailable() {
- for i := 0; i < nodemask.Len(); i++ {
- _, _, err := gonuma.NodeMemSize64(i)
- assert.Equal(syscall.ENOSYS, err)
- }
- } else {
- for i := 0; i < nodemask.Len(); i++ {
- if !nodemask.Get(i) {
- continue
- }
- total, freed, err := gonuma.NodeMemSize64(i)
- assert.NoError(err)
- assert.True(total > 0)
- assert.True(freed >= 0)
- }
- }
- }
- func TestNUMAAPI(t *testing.T) {
- assert := require.New(t)
- assert.True(gonuma.MaxNodeID() >= 0, "gonuma.MaxNodeID() >= 0")
- assert.True(
- gonuma.MaxPossibleNodeID() >= 0,
- "gonuma.MaxPossibleNodeID() >= 0",
- )
- assert.True(gonuma.MaxPossibleNodeID() >= gonuma.MaxNodeID())
- assert.True(gonuma.NodeCount() > 0, "NodeCount() > 0")
- assert.True(gonuma.NodePossibleCount() > 0, "NodePossibleCount() > 0")
- assert.True(gonuma.NodePossibleCount() >= gonuma.NodeCount())
- assert.True(gonuma.CPUCount() > 0)
- }
- func TestMemPolicy(t *testing.T) {
- if !gonuma.NUMAavailable() {
- t.Skip()
- }
- assert := require.New(t)
- t.Log("nnodemask = ", gonuma.NUMAnodemax)
- t.Log("NUMAconfigurednode =", gonuma.NUMAconfigurednode)
- t.Log("ncpumask =", gonuma.NUMAcpuMax)
- t.Log("nconfiguredcpu =", gonuma.NUMAconfiguredcpu)
- mode, _ := gonuma.GetMemPolicy(nil, nil, 0)
- // assert.NoError(err) // XXX(jhj): Test fails in Docker?!
- assert.True(mode >= 0 && mode < gonuma.MPolMax, "%#v", mode)
- // assert.NoError(gonuma.SetMemPolicy(gonuma.MPolDefault, nil)) // XXX(jhj): Test fails in Docker?!
- }
- // func TestGetMemAllowedNodeMaskAndBind(t *testing.T) {
- // assert := require.New(t)
- // mask, err := gonuma.GetMemAllowedNodeMask()
- // if gonuma.NUMAavailable() {
- // assert.NoError(err)
- // assert.True(mask.OnesCount() > 0)
- // assert.NoError(gonuma.Bind(mask))
- // } else {
- // assert.Equal(syscall.ENOSYS, err)
- // }
- // } // XXX(jhj): ^ above tests fail in Docker?!
- func TestRunOnNodeAndRunningNodesMask(t *testing.T) {
- if !gonuma.NUMAavailable() {
- t.Skip()
- }
- assert := require.New(t)
- mask, err := gonuma.RunningNodesMask()
- assert.NoError(err)
- assert.True(mask.OnesCount() > 0)
- for i := 0; i < mask.Len(); i++ {
- if !mask.Get(i) {
- continue
- }
- assert.NoError(gonuma.RunOnNode(i), "run on node %d", i)
- cpumask, err := gonuma.NodeToCPUMask(i)
- assert.NoError(err)
- assert.True(cpumask.OnesCount() > 0)
- gotmask, err := gonuma.RunningCPUMask()
- assert.NoError(err)
- assert.Equal(cpumask, gotmask)
- for j := 0; j < cpumask.Len(); j++ {
- if !cpumask.Get(j) {
- continue
- }
- node, err := gonuma.CPUToNode(j)
- assert.NoError(err)
- assert.Equal(i, node)
- }
- }
- assert.NoError(gonuma.RunOnNode(-1))
- assert.Error(gonuma.RunOnNode(-2))
- assert.Error(gonuma.RunOnNode(1 << 20))
- _, err = gonuma.CPUToNode(gonuma.CPUPossibleCount())
- assert.Error(err)
- }
- func TestMBind(t *testing.T) {
- if !gonuma.NUMAavailable() {
- t.Skip()
- }
- // assert := require.New(t) // XXX(jhj): Test fails in Docker?!
- // assert.Equal(syscall.EINVAL,
- // gonuma.MBind(unsafe.Pointer(t), 100, gonuma.MPolDefault, 0, nil)) // XXX(jhj): Test fails in Docker?!
- }
- func TestGetNodeAndCPU(t *testing.T) {
- if !gonuma.NUMAavailable() {
- t.Skip("not available")
- }
- var (
- nodem = gonuma.NewBitmask(gonuma.NodePossibleCount())
- mu sync.Mutex
- wg sync.WaitGroup
- assert = require.New(t)
- )
- cpum := make([]gonuma.Bitmask, gonuma.NodePossibleCount())
- for i := 0; i < len(cpum); i++ {
- cpum[i] = gonuma.NewBitmask(gonuma.CPUPossibleCount())
- }
- for i := 0; i < gonuma.CPUCount(); i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- for i := 0; i < 100; i++ {
- cpu, node := gonuma.GetCPUAndNode()
- mu.Lock()
- cpum[node].Set(cpu, true)
- nodem.Set(node, true)
- mu.Unlock()
- runtime.Gosched()
- }
- }()
- }
- wg.Wait()
- for i := 0; i < (gonuma.CPUCount() * 2); i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- cpu, node := gonuma.GetCPUAndNode()
- t.Logf("TestGetNodeAndCPU cpu %v node %v", cpu, node)
- }()
- }
- wg.Wait()
- nmask := gonuma.NodeMask()
- for i := 0; i < nodem.Len(); i++ {
- if !nodem.Get(i) {
- continue
- }
- assert.True(nmask.Get(i), "node %d", i)
- cpumask, err := gonuma.NodeToCPUMask(i)
- assert.NoError(err)
- cmask := cpum[i]
- for j := 0; j < cmask.Len(); j++ {
- if !cmask.Get(j) {
- continue
- }
- assert.True(cpumask.Get(j), "cpu %d @ node %d", j, i)
- }
- }
- }
- func BenchmarkGetCPUAndNode(b *testing.B) {
- b.RunParallel(func(bp *testing.PB) {
- for bp.Next() {
- gonuma.GetCPUAndNode()
- }
- })
- }
|