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

Recommend default_toast_compression=lz4 & jit=off #138

Merged
merged 1 commit into from
Nov 8, 2024
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
79 changes: 53 additions & 26 deletions pkg/pgtune/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const (
AutovacuumNaptimeKey = "autovacuum_naptime"
EffectiveIOKey = "effective_io_concurrency" // linux only

// nonnumeric
DefaultToastCompression = "default_toast_compression"
Jit = "jit"

checkpointDefault = "0.9"
statsTargetDefault = "100"
randomPageCostDefault = "1.1"
Expand All @@ -31,6 +35,8 @@ const (
// https://www.postgresql.org/message-id/20210422195232.GA25061%40momjian.us
effectiveIODefaultOldVersions = "200"
effectiveIODefault = "256"
lz4Compression = "lz4"
off = "off"

// If you want to lower this value, consider that Patroni will not accept anything less than 25 as
// a valid max_connections and will replace it with 100, per
Expand Down Expand Up @@ -59,12 +65,18 @@ func getMaxConns(totalMemory uint64) uint64 {
}
}

func getValueForVersion(currentVersion string, oldVersions []string, oldVersionValue, newVersionValue string) string {
for _, ov := range oldVersions {
if ov == currentVersion {
return oldVersionValue
}
}
return newVersionValue
}

func getEffectiveIOConcurrency(pgMajorVersion string) string {
switch pgMajorVersion {
case pgutils.MajorVersion96,
pgutils.MajorVersion10,
pgutils.MajorVersion11,
pgutils.MajorVersion12:
case pgutils.MajorVersion96, pgutils.MajorVersion10, pgutils.MajorVersion11, pgutils.MajorVersion12:
return effectiveIODefaultOldVersions
}
return effectiveIODefault
Expand All @@ -90,7 +102,10 @@ var MiscKeys = []string{
MaxLocksPerTxKey,
AutovacuumMaxWorkersKey,
AutovacuumNaptimeKey,
EffectiveIOKey,
DefaultToastCompression,
Jit,

EffectiveIOKey, //linux only
}

// MiscRecommender gives recommendations for MiscKeys based on system resources.
Expand All @@ -113,37 +128,49 @@ func (r *MiscRecommender) IsAvailable() bool {
// Recommend returns the recommended PostgreSQL formatted value for the conf
// file for a given key.
func (r *MiscRecommender) Recommend(key string) string {
var val string
if key == CheckpointKey {
val = checkpointDefault
} else if key == StatsTargetKey {
val = statsTargetDefault
} else if key == MaxConnectionsKey {
conns := getMaxConns(r.totalMemory)
switch key {
case CheckpointKey:
return checkpointDefault
case StatsTargetKey:
return statsTargetDefault
case AutovacuumMaxWorkersKey:
return autovacuumMaxWorkersDefault
case AutovacuumNaptimeKey:
return autovacuumNaptimeDefault
case RandomPageCostKey:
return randomPageCostDefault
case EffectiveIOKey:
return getValueForVersion(r.pgMajorVersion, []string{
pgutils.MajorVersion96, pgutils.MajorVersion10, pgutils.MajorVersion11, pgutils.MajorVersion12},
effectiveIODefaultOldVersions, effectiveIODefault,
)
case DefaultToastCompression:
return getValueForVersion(r.pgMajorVersion, []string{
pgutils.MajorVersion96, pgutils.MajorVersion10, pgutils.MajorVersion11, pgutils.MajorVersion12, pgutils.MajorVersion13},
NoRecommendation, lz4Compression,
)
case Jit:
return getValueForVersion(r.pgMajorVersion, []string{
pgutils.MajorVersion96, pgutils.MajorVersion10, pgutils.MajorVersion11},
NoRecommendation, off,
)
case MaxConnectionsKey:
if r.maxConns != 0 {
conns = r.maxConns
return fmt.Sprintf("%d", r.maxConns)
}
val = fmt.Sprintf("%d", conns)
} else if key == RandomPageCostKey {
val = randomPageCostDefault
} else if key == MaxLocksPerTxKey {
return fmt.Sprintf("%d", getMaxConns(r.totalMemory))
case MaxLocksPerTxKey:
for i := len(maxLocksValues) - 1; i >= 1; i-- {
limit := uint64(math.Pow(2.0, float64(2+i)))
if r.totalMemory >= limit*parse.Gigabyte {
return maxLocksValues[i]
}
}
return maxLocksValues[0]
} else if key == AutovacuumMaxWorkersKey {
val = autovacuumMaxWorkersDefault
} else if key == AutovacuumNaptimeKey {
val = autovacuumNaptimeDefault
} else if key == EffectiveIOKey {
val = getEffectiveIOConcurrency(r.pgMajorVersion)
} else {
val = NoRecommendation
}
return val

//unknown key no recommendation
return NoRecommendation
}

// MiscSettingsGroup is the SettingsGroup to represent settings that do not fit in other SettingsGroups.
Expand Down
64 changes: 63 additions & 1 deletion pkg/pgtune/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,68 @@ func TestGetEffectiveIOConcurrency(t *testing.T) {
}
}

func TestDefaultToastCompression(t *testing.T) {
cases := []struct {
pgMajorVersions []string
want string
}{
{
[]string{pgutils.MajorVersion96, pgutils.MajorVersion10, pgutils.MajorVersion11, pgutils.MajorVersion12, pgutils.MajorVersion13},
NoRecommendation,
},
{
[]string{pgutils.MajorVersion14, pgutils.MajorVersion15, pgutils.MajorVersion16, pgutils.MajorVersion17,
"18", //future versions
},
"lz4",
},
}
for _, c := range cases {
for _, v := range c.pgMajorVersions {
t.Run("default_toast_compression:"+v, func(t *testing.T) {
r := NewMiscRecommender(1000, 32, v)

rec := r.Recommend(DefaultToastCompression)
if rec != c.want {
t.Errorf("wanted %s got: %s", c.want, rec)
}

})
}
}
}

func TestJIT(t *testing.T) {
cases := []struct {
pgMajorVersions []string
want string
}{
{
[]string{pgutils.MajorVersion96, pgutils.MajorVersion10, pgutils.MajorVersion11},
NoRecommendation,
},
{
[]string{pgutils.MajorVersion12, pgutils.MajorVersion13, pgutils.MajorVersion14, pgutils.MajorVersion15, pgutils.MajorVersion16, pgutils.MajorVersion17,
"18", //future versions
},
"off",
},
}
for _, c := range cases {
for _, v := range c.pgMajorVersions {
t.Run("default_toast_compression:"+v, func(t *testing.T) {
r := NewMiscRecommender(1000, 32, v)

rec := r.Recommend(Jit)
if rec != c.want {
t.Errorf("wanted %s got: %s", c.want, rec)
}

})
}
}
}

func TestNewMiscRecommender(t *testing.T) {
for i := 0; i < 1000000; i++ {
mem := rand.Uint64()
Expand All @@ -173,7 +235,7 @@ func TestNewMiscRecommender(t *testing.T) {
func TestMiscRecommenderRecommend(t *testing.T) {
for totalMemory, outerMatrix := range miscSettingsMatrix {
for maxConns, matrix := range outerMatrix {
r := &MiscRecommender{totalMemory, maxConns, pgutils.MajorVersion12}
r := &MiscRecommender{totalMemory, maxConns, pgutils.MajorVersion10}
testRecommender(t, r, MiscKeys, matrix)
}
}
Expand Down
23 changes: 16 additions & 7 deletions pkg/tstune/tuner.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,26 +444,35 @@ func checkIfShouldShowSetting(keys []string, parseResults map[string]*tunablePar

rv := pgtune.GetFloatParser(recommender)

// get and parse our recommendation; fail if for we can't
rec := recommender.Recommend(k)

switch {
case rec == pgtune.NoRecommendation:
// don't bother adding it to the map. no recommendation
continue
case r.commented:
show[k] = true
case r.value == rec:
// don't bother adding it to the map. no recommendation
continue

}

// parse the value already there; if unparseable, should show our rec
curr, err := rv.ParseFloat(k, r.value)
if err != nil {
show[k] = true
continue
}

// get and parse our recommendation; fail if for we can't
rec := recommender.Recommend(k)
if rec == pgtune.NoRecommendation {
// don't bother adding it to the map. no recommendation
continue
}
target, err := rv.ParseFloat(k, rec)
if err != nil {
return nil, fmt.Errorf("unexpected parsing problem: %v", err)
}

// only show if our recommendation is significantly different, or config is commented
if !isCloseEnough(curr, target, fudgeFactor) || r.commented {
if !isCloseEnough(curr, target, fudgeFactor) {
show[k] = true
}
}
Expand Down
Loading
Loading