Skip to content

Commit 5c8b365

Browse files
committed
Adjust settings for promscale
Set wal_compression = 1 Set bgwriter_flush_after = 0 Set shared_buffers = 50% of total memory Do not recommend for bgwriter_delay or bgwriter_lru_maxpages
1 parent db830a3 commit 5c8b365

File tree

13 files changed

+396
-116
lines changed

13 files changed

+396
-116
lines changed

go.mod

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
module github.com/timescale/timescaledb-tune
22

3-
go 1.12
3+
go 1.18
44

55
require (
66
github.com/fatih/color v1.9.0
77
github.com/pbnjay/memory v0.0.0-20190104145345-974d429e7ae4
88
)
9+
10+
require (
11+
github.com/mattn/go-colorable v0.1.4 // indirect
12+
github.com/mattn/go-isatty v0.0.11 // indirect
13+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect
14+
)

pkg/pgtune/background_writer.go

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
package pgtune
22

3-
import "github.com/timescale/timescaledb-tune/internal/parse"
4-
53
const (
6-
BgwriterDelayKey = "bgwriter_delay"
7-
BgwriterLRUMaxPagesKey = "bgwriter_lru_maxpages"
4+
BgwriterFlushAfterKey = "bgwriter_flush_after"
85

9-
promscaleDefaultBgwriterDelay = "10ms"
10-
promscaleDefaultBgwriterLRUMaxPages = "100000"
6+
promscaleDefaultBgwriterFlushAfter = "0"
117
)
128

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

1612
var BgwriterKeys = []string{
17-
BgwriterDelayKey,
18-
BgwriterLRUMaxPagesKey,
13+
BgwriterFlushAfterKey,
1914
}
2015

2116
// PromscaleBgwriterRecommender gives recommendations for the background writer for the promscale profile
@@ -30,10 +25,8 @@ func (r *PromscaleBgwriterRecommender) IsAvailable() bool {
3025
// file for a given key.
3126
func (r *PromscaleBgwriterRecommender) Recommend(key string) string {
3227
switch key {
33-
case BgwriterDelayKey:
34-
return promscaleDefaultBgwriterDelay
35-
case BgwriterLRUMaxPagesKey:
36-
return promscaleDefaultBgwriterLRUMaxPages
28+
case BgwriterFlushAfterKey:
29+
return promscaleDefaultBgwriterFlushAfter
3730
default:
3831
return NoRecommendation
3932
}
@@ -61,23 +54,3 @@ func (sg *BgwriterSettingsGroup) GetRecommender(profile Profile) Recommender {
6154
return &NullRecommender{}
6255
}
6356
}
64-
65-
type BgwriterFloatParser struct{}
66-
67-
func (v *BgwriterFloatParser) ParseFloat(key string, s string) (float64, error) {
68-
switch key {
69-
case BgwriterDelayKey:
70-
val, units, err := parse.PGFormatToTime(s, parse.Milliseconds, parse.VarTypeInteger)
71-
if err != nil {
72-
return val, err
73-
}
74-
conv, err := parse.TimeConversion(units, parse.Milliseconds)
75-
if err != nil {
76-
return val, err
77-
}
78-
return val * conv, nil
79-
default:
80-
bfp := &numericFloatParser{}
81-
return bfp.ParseFloat(key, s)
82-
}
83-
}

pkg/pgtune/background_writer_test.go

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package pgtune
33
import (
44
"fmt"
55
"testing"
6-
7-
"github.com/timescale/timescaledb-tune/internal/parse"
86
)
97

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

3230
// the default profile should provide no recommendations
3331
r := sg.GetRecommender(DefaultProfile)
34-
if val := r.Recommend(BgwriterDelayKey); val != NoRecommendation {
35-
t.Errorf("Expected no recommendation for key %s but got %s", BgwriterDelayKey, val)
36-
}
37-
if val := r.Recommend(BgwriterLRUMaxPagesKey); val != NoRecommendation {
38-
t.Errorf("Expected no recommendation for key %s but got %s", BgwriterLRUMaxPagesKey, val)
32+
if val := r.Recommend(BgwriterFlushAfterKey); val != NoRecommendation {
33+
t.Errorf("Expected no recommendation for key %s but got %s", BgwriterFlushAfterKey, val)
3934
}
4035

4136
// the promscale profile should have recommendations
4237
r = sg.GetRecommender(PromscaleProfile)
43-
if val := r.Recommend(BgwriterDelayKey); val != promscaleDefaultBgwriterDelay {
44-
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterDelay, BgwriterDelayKey, val)
45-
}
46-
if val := r.Recommend(BgwriterLRUMaxPagesKey); val != promscaleDefaultBgwriterLRUMaxPages {
47-
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterLRUMaxPages, BgwriterLRUMaxPagesKey, val)
38+
if val := r.Recommend(BgwriterFlushAfterKey); val != promscaleDefaultBgwriterFlushAfter {
39+
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterFlushAfter, BgwriterFlushAfterKey, val)
4840
}
4941
}
5042

@@ -53,35 +45,7 @@ func TestPromscaleBgwriterRecommender(t *testing.T) {
5345
if !r.IsAvailable() {
5446
t.Error("PromscaleBgwriterRecommender should always be available")
5547
}
56-
if val := r.Recommend(BgwriterDelayKey); val != promscaleDefaultBgwriterDelay {
57-
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterDelay, BgwriterDelayKey, val)
58-
}
59-
if val := r.Recommend(BgwriterLRUMaxPagesKey); val != promscaleDefaultBgwriterLRUMaxPages {
60-
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterLRUMaxPages, BgwriterLRUMaxPagesKey, val)
61-
}
62-
}
63-
64-
func TestBgwriterFloatParserParseFloat(t *testing.T) {
65-
v := &BgwriterFloatParser{}
66-
67-
s := "100"
68-
want := 100.0
69-
got, err := v.ParseFloat(BgwriterLRUMaxPagesKey, s)
70-
if err != nil {
71-
t.Errorf("unexpected error: %v", err)
72-
}
73-
if got != want {
74-
t.Errorf("incorrect result: got %f want %f", got, want)
75-
}
76-
77-
s = "33" + parse.Minutes.String()
78-
conversion, _ := parse.TimeConversion(parse.Minutes, parse.Milliseconds)
79-
want = 33.0 * conversion
80-
got, err = v.ParseFloat(BgwriterDelayKey, s)
81-
if err != nil {
82-
t.Errorf("unexpected error: %v", err)
83-
}
84-
if got != want {
85-
t.Errorf("incorrect result: got %f want %f", got, want)
48+
if val := r.Recommend(BgwriterFlushAfterKey); val != promscaleDefaultBgwriterFlushAfter {
49+
t.Errorf("Expected %s for key %s but got %s", promscaleDefaultBgwriterFlushAfter, BgwriterFlushAfterKey, val)
8650
}
8751
}

pkg/pgtune/float_parser.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package pgtune
22

33
import (
4+
"fmt"
45
"strconv"
6+
"strings"
57

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

11+
const (
12+
errUnrecognizedBoolValue = "unrecognized bool value: %s"
13+
)
14+
915
type FloatParser interface {
1016
ParseFloat(string, string) (float64, error)
1117
}
@@ -23,6 +29,34 @@ func (v *numericFloatParser) ParseFloat(key string, s string) (float64, error) {
2329
return strconv.ParseFloat(s, 64)
2430
}
2531

32+
type boolFloatParser struct{}
33+
34+
func (v *boolFloatParser) ParseFloat(key string, s string) (float64, error) {
35+
s = strings.ToLower(s)
36+
s = strings.TrimLeft(s, `"'`)
37+
s = strings.TrimRight(s, `"'`)
38+
switch s {
39+
case "on":
40+
return 1.0, nil
41+
case "off":
42+
return 0.0, nil
43+
case "true":
44+
return 1.0, nil
45+
case "false":
46+
return 0.0, nil
47+
case "yes":
48+
return 1.0, nil
49+
case "no":
50+
return 0.0, nil
51+
case "1":
52+
return 1.0, nil
53+
case "0":
54+
return 0.0, nil
55+
default:
56+
return 0.0, fmt.Errorf(errUnrecognizedBoolValue, s)
57+
}
58+
}
59+
2660
// GetFloatParser returns the correct FloatParser for a given Recommender.
2761
func GetFloatParser(r Recommender) FloatParser {
2862
switch r.(type) {
@@ -33,7 +67,7 @@ func GetFloatParser(r Recommender) FloatParser {
3367
case *PromscaleWALRecommender:
3468
return &WALFloatParser{}
3569
case *PromscaleBgwriterRecommender:
36-
return &BgwriterFloatParser{}
70+
return &numericFloatParser{}
3771
case *ParallelRecommender:
3872
return &numericFloatParser{}
3973
default:

pkg/pgtune/float_parser_test.go

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,119 @@ func TestNumericFloatParserParseFloat(t *testing.T) {
3232
}
3333
}
3434

35+
func Test_boolFloatParser_ParseFloat(t *testing.T) {
36+
tests := []struct {
37+
name string
38+
arg string
39+
want float64
40+
wantErr bool
41+
}{
42+
{
43+
name: "on",
44+
arg: "on",
45+
want: 1.0,
46+
wantErr: false,
47+
},
48+
{
49+
name: "oN",
50+
arg: "oN",
51+
want: 1.0,
52+
wantErr: false,
53+
},
54+
{
55+
name: "'ON'",
56+
arg: "'ON'",
57+
want: 1.0,
58+
wantErr: false,
59+
},
60+
{
61+
name: "off",
62+
arg: "off",
63+
want: 0.0,
64+
wantErr: false,
65+
},
66+
{
67+
name: "OfF",
68+
arg: "OfF",
69+
want: 0.0,
70+
wantErr: false,
71+
},
72+
{
73+
name: "'OFF'",
74+
arg: "'OFF'",
75+
want: 0.0,
76+
wantErr: false,
77+
},
78+
{
79+
name: "true",
80+
arg: "true",
81+
want: 1.0,
82+
wantErr: false,
83+
},
84+
{
85+
name: "false",
86+
arg: "false",
87+
want: 0.0,
88+
wantErr: false,
89+
},
90+
{
91+
name: "yes",
92+
arg: "yes",
93+
want: 1.0,
94+
wantErr: false,
95+
},
96+
{
97+
name: "no",
98+
arg: "no",
99+
want: 0.0,
100+
wantErr: false,
101+
},
102+
{
103+
name: "1",
104+
arg: "1",
105+
want: 1.0,
106+
wantErr: false,
107+
},
108+
{
109+
name: "0",
110+
arg: "0",
111+
want: 0.0,
112+
wantErr: false,
113+
},
114+
{
115+
name: "bob",
116+
arg: "bob",
117+
want: 0.0,
118+
wantErr: true,
119+
},
120+
{
121+
name: "99",
122+
arg: "99",
123+
want: 0.0,
124+
wantErr: true,
125+
},
126+
{
127+
name: "0.1",
128+
arg: "0.1",
129+
want: 0.0,
130+
wantErr: true,
131+
},
132+
}
133+
for _, tt := range tests {
134+
t.Run(tt.name, func(t *testing.T) {
135+
v := &boolFloatParser{}
136+
got, err := v.ParseFloat("", tt.arg)
137+
if (err != nil) != tt.wantErr {
138+
t.Errorf("ParseFloat() error = %v, wantErr %v", err, tt.wantErr)
139+
return
140+
}
141+
if got != tt.want {
142+
t.Errorf("ParseFloat() got = %v, want %v", got, tt.want)
143+
}
144+
})
145+
}
146+
}
147+
35148
func TestGetFloatParser(t *testing.T) {
36149
switch x := (GetFloatParser(&MemoryRecommender{})).(type) {
37150
case *bytesFloatParser:
@@ -58,7 +171,7 @@ func TestGetFloatParser(t *testing.T) {
58171
}
59172

60173
switch x := (GetFloatParser(&PromscaleBgwriterRecommender{})).(type) {
61-
case *BgwriterFloatParser:
174+
case *numericFloatParser:
62175
default:
63176
t.Errorf("wrong validator type for PromscaleBgwriterRecommender: got %T", x)
64177
}

pkg/pgtune/memory.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,41 @@ func (r *MemoryRecommender) recommendWindows() string {
111111
return parse.BytesToPGFormat(temp)
112112
}
113113

114+
// PromscaleMemoryRecommender gives recommendations for ParallelKeys based on system resources
115+
type PromscaleMemoryRecommender struct {
116+
*MemoryRecommender
117+
}
118+
119+
// NewPromscaleMemoryRecommender returns a PromscaleMemoryRecommender that recommends based on the given
120+
// number of cpus and system memory
121+
func NewPromscaleMemoryRecommender(totalMemory uint64, cpus int, maxConns uint64) *PromscaleMemoryRecommender {
122+
return &PromscaleMemoryRecommender{
123+
MemoryRecommender: NewMemoryRecommender(totalMemory, cpus, maxConns),
124+
}
125+
}
126+
127+
// IsAvailable returns whether this Recommender is usable given the system resources. Always true.
128+
func (r *PromscaleMemoryRecommender) IsAvailable() bool {
129+
return true
130+
}
131+
132+
// Recommend returns the recommended PostgreSQL formatted value for the conf
133+
// file for a given key.
134+
func (r *PromscaleMemoryRecommender) Recommend(key string) string {
135+
var val string
136+
switch key {
137+
case SharedBuffersKey:
138+
if runtime.GOOS == osWindows {
139+
val = parse.BytesToPGFormat(sharedBuffersWindows)
140+
} else {
141+
val = parse.BytesToPGFormat(r.totalMemory / 2)
142+
}
143+
default:
144+
val = r.MemoryRecommender.Recommend(key)
145+
}
146+
return val
147+
}
148+
114149
// MemorySettingsGroup is the SettingsGroup to represent settings that affect memory usage.
115150
type MemorySettingsGroup struct {
116151
totalMemory uint64
@@ -126,5 +161,10 @@ func (sg *MemorySettingsGroup) Keys() []string { return MemoryKeys }
126161

127162
// GetRecommender should return a new MemoryRecommender.
128163
func (sg *MemorySettingsGroup) GetRecommender(profile Profile) Recommender {
129-
return NewMemoryRecommender(sg.totalMemory, sg.cpus, sg.maxConns)
164+
switch profile {
165+
case PromscaleProfile:
166+
return NewPromscaleMemoryRecommender(sg.totalMemory, sg.cpus, sg.maxConns)
167+
default:
168+
return NewMemoryRecommender(sg.totalMemory, sg.cpus, sg.maxConns)
169+
}
130170
}

0 commit comments

Comments
 (0)