Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gogctuner: support Max/Min GOGC #39109

Merged
merged 6 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions util/gctuner/tuner.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,37 @@ import (
"github.com/pingcap/tidb/util"
)

var (
maxGCPercent atomic.Uint32
minGCPercent atomic.Uint32

// EnableGOGCTuner is to control whether enable the GOGC tuner.
EnableGOGCTuner atomic.Bool

defaultGCPercent uint32 = 100
)

const (
// MaxGCPercent is the default max cost of memory.
MaxGCPercent uint32 = 500
// MinGCPercent is the default min cost of memory.
MinGCPercent uint32 = 100
defaultMaxGCPercent uint32 = 500
defaultMinGCPercent uint32 = 100
)

var defaultGCPercent uint32 = 100
// SetMaxGCPercent sets the max cost of memory.
func SetMaxGCPercent(percent uint32) {
maxGCPercent.Store(percent)
}

// EnableGOGCTuner is to control whether enable the GOGC tuner.
var EnableGOGCTuner atomic.Bool
// 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.
Expand Down Expand Up @@ -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
}
24 changes: 12 additions & 12 deletions util/gctuner/tuner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,40 +37,40 @@ 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
testHeap = make([]byte, threshold/2)
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
testHeap = make([]byte, threshold/4*3)
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
testHeap = make([]byte, threshold+1024)
runtime.GC()
for i := 0; i < 100; i++ {
runtime.GC()
require.Equal(t, MinGCPercent, tn.getGCPercent())
require.Equal(t, minGCPercent.Load(), tn.getGCPercent())
}
}

Expand All @@ -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))
}