Skip to content

Commit

Permalink
Adjust settings for promscale
Browse files Browse the repository at this point in the history
Set wal_compression = 1
Set bgwriter_flush_after = 0
Do not recommend for bgwriter_delay or bgwriter_lru_maxpages
  • Loading branch information
jgpruitt committed Dec 9, 2022
1 parent db830a3 commit 2c31848
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 98 deletions.
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
module github.com/timescale/timescaledb-tune

go 1.12
go 1.18

require (
github.com/fatih/color v1.9.0
github.com/pbnjay/memory v0.0.0-20190104145345-974d429e7ae4
)

require (
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.11 // indirect
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect
)
37 changes: 5 additions & 32 deletions pkg/pgtune/background_writer.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
package pgtune

import "github.com/timescale/timescaledb-tune/internal/parse"

const (
BgwriterDelayKey = "bgwriter_delay"
BgwriterLRUMaxPagesKey = "bgwriter_lru_maxpages"
BgwriterFlushAfterKey = "bgwriter_flush_after"

promscaleDefaultBgwriterDelay = "10ms"
promscaleDefaultBgwriterLRUMaxPages = "100000"
promscaleDefaultBgwriterFlushAfter = "0"
)

// BgwriterLabel is the label used to refer to the background writer settings group
const BgwriterLabel = "background writer"

var BgwriterKeys = []string{
BgwriterDelayKey,
BgwriterLRUMaxPagesKey,
BgwriterFlushAfterKey,
}

// PromscaleBgwriterRecommender gives recommendations for the background writer for the promscale profile
Expand All @@ -30,10 +25,8 @@ func (r *PromscaleBgwriterRecommender) IsAvailable() bool {
// file for a given key.
func (r *PromscaleBgwriterRecommender) Recommend(key string) string {
switch key {
case BgwriterDelayKey:
return promscaleDefaultBgwriterDelay
case BgwriterLRUMaxPagesKey:
return promscaleDefaultBgwriterLRUMaxPages
case BgwriterFlushAfterKey:
return promscaleDefaultBgwriterFlushAfter
default:
return NoRecommendation
}
Expand Down Expand Up @@ -61,23 +54,3 @@ func (sg *BgwriterSettingsGroup) GetRecommender(profile Profile) Recommender {
return &NullRecommender{}
}
}

type BgwriterFloatParser struct{}

func (v *BgwriterFloatParser) ParseFloat(key string, s string) (float64, error) {
switch key {
case BgwriterDelayKey:
val, units, err := parse.PGFormatToTime(s, parse.Milliseconds, parse.VarTypeInteger)
if err != nil {
return val, err
}
conv, err := parse.TimeConversion(units, parse.Milliseconds)
if err != nil {
return val, err
}
return val * conv, nil
default:
bfp := &numericFloatParser{}
return bfp.ParseFloat(key, s)
}
}
48 changes: 6 additions & 42 deletions pkg/pgtune/background_writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package pgtune
import (
"fmt"
"testing"

"github.com/timescale/timescaledb-tune/internal/parse"
)

func TestBgwriterSettingsGroup_GetRecommender(t *testing.T) {
Expand All @@ -31,20 +29,14 @@ func TestBgwriterSettingsGroupRecommend(t *testing.T) {

// the default profile should provide no recommendations
r := sg.GetRecommender(DefaultProfile)
if val := r.Recommend(BgwriterDelayKey); val != NoRecommendation {
t.Errorf("Expected no recommendation for key %s but got %s", BgwriterDelayKey, val)
}
if val := r.Recommend(BgwriterLRUMaxPagesKey); val != NoRecommendation {
t.Errorf("Expected no recommendation for key %s but got %s", BgwriterLRUMaxPagesKey, val)
if val := r.Recommend(BgwriterFlushAfterKey); val != NoRecommendation {
t.Errorf("Expected no recommendation for key %s but got %s", BgwriterFlushAfterKey, val)
}

// the promscale profile should have recommendations
r = sg.GetRecommender(PromscaleProfile)
if val := r.Recommend(BgwriterDelayKey); val != promscaleDefaultBgwriterDelay {
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterDelay, BgwriterDelayKey, val)
}
if val := r.Recommend(BgwriterLRUMaxPagesKey); val != promscaleDefaultBgwriterLRUMaxPages {
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterLRUMaxPages, BgwriterLRUMaxPagesKey, val)
if val := r.Recommend(BgwriterFlushAfterKey); val != promscaleDefaultBgwriterFlushAfter {
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterFlushAfter, BgwriterFlushAfterKey, val)
}
}

Expand All @@ -53,35 +45,7 @@ func TestPromscaleBgwriterRecommender(t *testing.T) {
if !r.IsAvailable() {
t.Error("PromscaleBgwriterRecommender should always be available")
}
if val := r.Recommend(BgwriterDelayKey); val != promscaleDefaultBgwriterDelay {
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterDelay, BgwriterDelayKey, val)
}
if val := r.Recommend(BgwriterLRUMaxPagesKey); val != promscaleDefaultBgwriterLRUMaxPages {
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterLRUMaxPages, BgwriterLRUMaxPagesKey, val)
}
}

func TestBgwriterFloatParserParseFloat(t *testing.T) {
v := &BgwriterFloatParser{}

s := "100"
want := 100.0
got, err := v.ParseFloat(BgwriterLRUMaxPagesKey, s)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if got != want {
t.Errorf("incorrect result: got %f want %f", got, want)
}

s = "33" + parse.Minutes.String()
conversion, _ := parse.TimeConversion(parse.Minutes, parse.Milliseconds)
want = 33.0 * conversion
got, err = v.ParseFloat(BgwriterDelayKey, s)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if got != want {
t.Errorf("incorrect result: got %f want %f", got, want)
if val := r.Recommend(BgwriterFlushAfterKey); val != promscaleDefaultBgwriterFlushAfter {
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterFlushAfter, BgwriterFlushAfterKey, val)
}
}
36 changes: 35 additions & 1 deletion pkg/pgtune/float_parser.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package pgtune

import (
"fmt"
"strconv"
"strings"

"github.com/timescale/timescaledb-tune/internal/parse"
)

const (
errUnrecognizedBoolValue = "unrecognized bool value: %s"
)

type FloatParser interface {
ParseFloat(string, string) (float64, error)
}
Expand All @@ -23,6 +29,34 @@ func (v *numericFloatParser) ParseFloat(key string, s string) (float64, error) {
return strconv.ParseFloat(s, 64)
}

type boolFloatParser struct{}

func (v *boolFloatParser) ParseFloat(key string, s string) (float64, error) {
s = strings.ToLower(s)
s = strings.TrimLeft(s, `"'`)
s = strings.TrimRight(s, `"'`)
switch s {
case "on":
return 1.0, nil
case "off":
return 0.0, nil
case "true":
return 1.0, nil
case "false":
return 0.0, nil
case "yes":
return 1.0, nil
case "no":
return 0.0, nil
case "1":
return 1.0, nil
case "0":
return 0.0, nil
default:
return 0.0, fmt.Errorf(errUnrecognizedBoolValue, s)
}
}

// GetFloatParser returns the correct FloatParser for a given Recommender.
func GetFloatParser(r Recommender) FloatParser {
switch r.(type) {
Expand All @@ -33,7 +67,7 @@ func GetFloatParser(r Recommender) FloatParser {
case *PromscaleWALRecommender:
return &WALFloatParser{}
case *PromscaleBgwriterRecommender:
return &BgwriterFloatParser{}
return &numericFloatParser{}
case *ParallelRecommender:
return &numericFloatParser{}
default:
Expand Down
115 changes: 114 additions & 1 deletion pkg/pgtune/float_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,119 @@ func TestNumericFloatParserParseFloat(t *testing.T) {
}
}

func Test_boolFloatParser_ParseFloat(t *testing.T) {
tests := []struct {
name string
arg string
want float64
wantErr bool
}{
{
name: "on",
arg: "on",
want: 1.0,
wantErr: false,
},
{
name: "oN",
arg: "oN",
want: 1.0,
wantErr: false,
},
{
name: "'ON'",
arg: "'ON'",
want: 1.0,
wantErr: false,
},
{
name: "off",
arg: "off",
want: 0.0,
wantErr: false,
},
{
name: "OfF",
arg: "OfF",
want: 0.0,
wantErr: false,
},
{
name: "'OFF'",
arg: "'OFF'",
want: 0.0,
wantErr: false,
},
{
name: "true",
arg: "true",
want: 1.0,
wantErr: false,
},
{
name: "false",
arg: "false",
want: 0.0,
wantErr: false,
},
{
name: "yes",
arg: "yes",
want: 1.0,
wantErr: false,
},
{
name: "no",
arg: "no",
want: 0.0,
wantErr: false,
},
{
name: "1",
arg: "1",
want: 1.0,
wantErr: false,
},
{
name: "0",
arg: "0",
want: 0.0,
wantErr: false,
},
{
name: "bob",
arg: "bob",
want: 0.0,
wantErr: true,
},
{
name: "99",
arg: "99",
want: 0.0,
wantErr: true,
},
{
name: "0.1",
arg: "0.1",
want: 0.0,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v := &boolFloatParser{}
got, err := v.ParseFloat("", tt.arg)
if (err != nil) != tt.wantErr {
t.Errorf("ParseFloat() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("ParseFloat() got = %v, want %v", got, tt.want)
}
})
}
}

func TestGetFloatParser(t *testing.T) {
switch x := (GetFloatParser(&MemoryRecommender{})).(type) {
case *bytesFloatParser:
Expand All @@ -58,7 +171,7 @@ func TestGetFloatParser(t *testing.T) {
}

switch x := (GetFloatParser(&PromscaleBgwriterRecommender{})).(type) {
case *BgwriterFloatParser:
case *numericFloatParser:
default:
t.Errorf("wrong validator type for PromscaleBgwriterRecommender: got %T", x)
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/pgtune/wal.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ const (
MinWALKey = "min_wal_size"
MaxWALKey = "max_wal_size"
CheckpointTimeoutKey = "checkpoint_timeout"
WALCompressionKey = "wal_compression"

walMaxDiskPct = 60 // max_wal_size should be 60% of the WAL disk
walBuffersThreshold = 2 * parse.Gigabyte
walBuffersDefault = 16 * parse.Megabyte
defaultMaxWALBytes = 1 * parse.Gigabyte
promscaleDefaultMaxWALBytes = 4 * parse.Gigabyte
promscaleDefaultCheckpointTimeout = "900" // 15 minutes expressed in seconds
promscaleDefaultWALCompression = "1"
)

// WALLabel is the label used to refer to the WAL settings group
Expand All @@ -28,6 +30,7 @@ var WALKeys = []string{
MinWALKey,
MaxWALKey,
CheckpointTimeoutKey,
WALCompressionKey,
}

// WALRecommender gives recommendations for WALKeys based on system resources
Expand Down Expand Up @@ -146,6 +149,8 @@ func (r *PromscaleWALRecommender) Recommend(key string) string {
return parse.BytesToPGFormat(temp)
case CheckpointTimeoutKey:
return promscaleDefaultCheckpointTimeout
case WALCompressionKey:
return promscaleDefaultWALCompression
default:
return r.WALRecommender.Recommend(key)
}
Expand Down Expand Up @@ -173,6 +178,9 @@ type WALFloatParser struct{}

func (v *WALFloatParser) ParseFloat(key string, s string) (float64, error) {
switch key {
case WALCompressionKey:
bfp := &boolFloatParser{}
return bfp.ParseFloat(key, s)
case CheckpointTimeoutKey:
val, units, err := parse.PGFormatToTime(s, parse.Milliseconds, parse.VarTypeInteger)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/pgtune/wal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func init() {
walSettingsMatrix[memory][walSize][MaxWALKey] = parse.BytesToPGFormat(walDiskToMaxBytes[walSize])
walSettingsMatrix[memory][walSize][WALBuffersKey] = parse.BytesToPGFormat(walBuffers)
walSettingsMatrix[memory][walSize][CheckpointTimeoutKey] = NoRecommendation
walSettingsMatrix[memory][walSize][WALCompressionKey] = NoRecommendation
}
}

Expand All @@ -64,6 +65,7 @@ func init() {
promscaleWalSettingsMatrix[memory][walSize][MaxWALKey] = parse.BytesToPGFormat(promscaleWALDiskToMaxBytes[walSize])
promscaleWalSettingsMatrix[memory][walSize][WALBuffersKey] = parse.BytesToPGFormat(walBuffers)
promscaleWalSettingsMatrix[memory][walSize][CheckpointTimeoutKey] = promscaleDefaultCheckpointTimeout
promscaleWalSettingsMatrix[memory][walSize][WALCompressionKey] = promscaleDefaultWALCompression
}
}
}
Expand Down
Loading

0 comments on commit 2c31848

Please sign in to comment.