gogctuner: support Max/Min GOGC (#39109)

close pingcap/tidb#39110
This commit is contained in:
Weizhen Wang
2022-11-14 16:41:54 +08:00
committed by GitHub
parent efa7010853
commit 4dd00bcae2
2 changed files with 40 additions and 25 deletions

View File

@ -23,22 +23,37 @@ import (
"github.com/pingcap/tidb/util"
)
const (
// MaxGCPercent is the default max cost of memory.
MaxGCPercent uint32 = 500
// MinGCPercent is the default min cost of memory.
MinGCPercent uint32 = 100
var (
maxGCPercent atomic.Uint32
minGCPercent atomic.Uint32
// EnableGOGCTuner is to control whether enable the GOGC tuner.
EnableGOGCTuner atomic.Bool
defaultGCPercent uint32 = 100
)
var defaultGCPercent uint32 = 100
const (
defaultMaxGCPercent uint32 = 500
defaultMinGCPercent uint32 = 100
)
// EnableGOGCTuner is to control whether enable the GOGC tuner.
var EnableGOGCTuner atomic.Bool
// SetMaxGCPercent sets the max cost of memory.
func SetMaxGCPercent(percent uint32) {
maxGCPercent.Store(percent)
}
// SetMinGCPercent sets the max cost of memory.
func SetMinGCPercent(percent uint32) {
minGCPercent.Store(percent)
}
func init() {
if val, err := strconv.Atoi(os.Getenv("GOGC")); err == nil {
defaultGCPercent = uint32(val)
}
SetMinGCPercent(defaultMinGCPercent)
SetMaxGCPercent(defaultMaxGCPercent)
}
// SetDefaultGOGC is to set the default GOGC value.
@ -151,13 +166,13 @@ func calcGCPercent(inuse, threshold uint64) uint32 {
}
// inuse heap larger than threshold, use min percent
if threshold <= inuse {
return MinGCPercent
return minGCPercent.Load()
}
gcPercent := uint32(math.Floor(float64(threshold-inuse) / float64(inuse) * 100))
if gcPercent < MinGCPercent {
return MinGCPercent
} else if gcPercent > MaxGCPercent {
return MaxGCPercent
if gcPercent < minGCPercent.Load() {
return minGCPercent.Load()
} else if gcPercent > maxGCPercent.Load() {
return maxGCPercent.Load()
}
return gcPercent
}

View File

@ -37,15 +37,15 @@ func TestTuner(t *testing.T) {
runtime.GC()
for i := 0; i < 100; i++ {
runtime.GC()
require.Equal(t, MaxGCPercent, tn.getGCPercent())
require.Equal(t, maxGCPercent.Load(), tn.getGCPercent())
}
// 1/4 threshold
testHeap = make([]byte, threshold/4)
for i := 0; i < 100; i++ {
runtime.GC()
require.GreaterOrEqual(t, tn.getGCPercent(), MaxGCPercent/2)
require.LessOrEqual(t, tn.getGCPercent(), MaxGCPercent)
require.GreaterOrEqual(t, tn.getGCPercent(), maxGCPercent.Load()/2)
require.LessOrEqual(t, tn.getGCPercent(), maxGCPercent.Load())
}
// 1/2 threshold
@ -53,8 +53,8 @@ func TestTuner(t *testing.T) {
runtime.GC()
for i := 0; i < 100; i++ {
runtime.GC()
require.GreaterOrEqual(t, tn.getGCPercent(), MinGCPercent)
require.LessOrEqual(t, tn.getGCPercent(), MaxGCPercent/2)
require.GreaterOrEqual(t, tn.getGCPercent(), minGCPercent.Load())
require.LessOrEqual(t, tn.getGCPercent(), maxGCPercent.Load()/2)
}
// 3/4 threshold
@ -62,7 +62,7 @@ func TestTuner(t *testing.T) {
runtime.GC()
for i := 0; i < 100; i++ {
runtime.GC()
require.Equal(t, MinGCPercent, tn.getGCPercent())
require.Equal(t, minGCPercent.Load(), tn.getGCPercent())
}
// out of threshold
@ -70,7 +70,7 @@ func TestTuner(t *testing.T) {
runtime.GC()
for i := 0; i < 100; i++ {
runtime.GC()
require.Equal(t, MinGCPercent, tn.getGCPercent())
require.Equal(t, minGCPercent.Load(), tn.getGCPercent())
}
}
@ -81,13 +81,13 @@ func TestCalcGCPercent(t *testing.T) {
require.Equal(t, defaultGCPercent, calcGCPercent(0, 1))
require.Equal(t, defaultGCPercent, calcGCPercent(1, 0))
require.Equal(t, MaxGCPercent, calcGCPercent(1, 3*gb))
require.Equal(t, MaxGCPercent, calcGCPercent(gb/10, 4*gb))
require.Equal(t, MaxGCPercent, calcGCPercent(gb/2, 4*gb))
require.Equal(t, maxGCPercent.Load(), calcGCPercent(1, 3*gb))
require.Equal(t, maxGCPercent.Load(), calcGCPercent(gb/10, 4*gb))
require.Equal(t, maxGCPercent.Load(), calcGCPercent(gb/2, 4*gb))
require.Equal(t, uint32(300), calcGCPercent(1*gb, 4*gb))
require.Equal(t, uint32(166), calcGCPercent(1.5*gb, 4*gb))
require.Equal(t, uint32(100), calcGCPercent(2*gb, 4*gb))
require.Equal(t, uint32(100), calcGCPercent(3*gb, 4*gb))
require.Equal(t, MinGCPercent, calcGCPercent(4*gb, 4*gb))
require.Equal(t, MinGCPercent, calcGCPercent(5*gb, 4*gb))
require.Equal(t, minGCPercent.Load(), calcGCPercent(4*gb, 4*gb))
require.Equal(t, minGCPercent.Load(), calcGCPercent(5*gb, 4*gb))
}