Fix utils.AdjustGoMaxProcs

Since Go 1.5, Go will use the total number of logical processers that the
system has available. Caveats to this are if someone has set the
GOMAXPROCS env var set or wish to limit usage of the number of logical processers
between a range from 1 to NumCPUs
This commit is contained in:
Adrian Gallagher
2019-10-03 10:12:44 +10:00
parent db317a2447
commit 8ca1e5c36f
4 changed files with 68 additions and 16 deletions

View File

@@ -16,16 +16,29 @@ var (
)
// AdjustGoMaxProcs sets the runtime GOMAXPROCS val
func AdjustGoMaxProcs(maxProcs int) error {
// Since Go 1.5, Go will use the total number of logical processers that the
// system has available. Caveats to this are if someone has set the GOMAXPROCS
// env var set or wish to limit usage of the number of logical processers
// between a range from 1 to NumCPUs
func AdjustGoMaxProcs(procs int) error {
// Check for default settings, plus respecting GOMAXPROCS env but
// don't allow for values which will cause thread contention
n := runtime.NumCPU()
if maxProcs < 0 || maxProcs > n {
maxProcs = n
if procs == runtime.GOMAXPROCS(-1) {
if procs <= n {
return nil
}
}
if i := runtime.GOMAXPROCS(maxProcs); i != maxProcs {
// Sanitise the procs value (defaults to NumCPUs)
if procs < 1 || procs > n {
procs = n
}
runtime.GOMAXPROCS(procs)
if i := runtime.GOMAXPROCS(procs); i != procs {
return ErrGoMaxProcsFailure
}
return nil
}

View File

@@ -1,22 +1,57 @@
package utils
import (
"fmt"
"runtime"
"testing"
)
func TestAdjustGoMaxProcs(t *testing.T) {
// Ensure that a supplied crazy number is set to a valid one and doesn't
// return an error
err := AdjustGoMaxProcs(1000)
if err != nil {
t.Fatalf("TestAdjustGoMaxProcs returned err: %v", err)
// Test default settings
curr := runtime.GOMAXPROCS(-1)
numCPUs := runtime.NumCPU()
// This func both checks for an error of AdjustGoMaxProcs, plus
// ensures that the value it sets is the one that is expected
checker := func(setting, expected int) error {
if err := AdjustGoMaxProcs(setting); err != nil {
return err
}
if i := runtime.GOMAXPROCS(expected); i != expected {
return fmt.Errorf("expected %d, got %d", expected, i)
}
return nil
}
// This time use the num of logical CPU's and ensure it doesn't
// return an error
err = AdjustGoMaxProcs(runtime.NumCPU())
if err != nil {
t.Fatalf("TestAdjustGoMaxProcs returned err: %v", err)
tester := []struct {
Setting int
Expected int
}{
{
// Test setting to current runtime val
Setting: curr,
Expected: curr,
},
{
// Test setting to num of logical CPUs
Setting: numCPUs,
Expected: numCPUs,
},
{
// Test crazy value and make sure it defaults to numCPUs
Setting: 1000,
Expected: numCPUs,
},
{
// Test another crazy value and make sure it defaults to numCPUs
Setting: -1,
Expected: numCPUs,
},
}
for x := range tester {
if err := checker(tester[x].Setting, tester[x].Expected); err != nil {
t.Errorf("%d failed. %s", tester[x], err)
}
}
}