1
1
package load
2
2
3
3
import (
4
+ "encoding/json"
4
5
"fmt"
5
6
"github.com/timescale/tsbs/pkg/targets"
7
+ "io/ioutil"
6
8
"log"
7
9
"math/rand"
8
10
"sync"
@@ -29,21 +31,22 @@ var (
29
31
30
32
// BenchmarkRunnerConfig contains all the configuration information required for running BenchmarkRunner.
31
33
type BenchmarkRunnerConfig struct {
32
- DBName string `yaml:"db-name" mapstructure:"db-name"`
33
- BatchSize uint `yaml:"batch-size" mapstructure:"batch-size"`
34
- Workers uint `yaml:"workers" mapstructure:"workers"`
35
- Limit uint64 `yaml:"limit" mapstructure:"limit"`
36
- DoLoad bool `yaml:"do-load" mapstructure:"do-load"`
37
- DoCreateDB bool `yaml:"do-create-db" mapstructure:"do-create-db"`
38
- DoAbortOnExist bool `yaml:"do-abort-on-exist" mapstructure:"do-abort-on-exist"`
39
- ReportingPeriod time.Duration `yaml:"reporting-period" mapstructure:"reporting-period"`
40
- HashWorkers bool `yaml:"hash-workers" mapstructure:"hash-workers"`
41
- NoFlowControl bool `yaml:"no-flow-control" mapstructure:"no-flow-control"`
42
- ChannelCapacity uint `yaml:"channel-capacity" mapstructure:"channel-capacity"`
43
- InsertIntervals string `yaml:"insert-intervals" mapstructure:"insert-intervals"`
34
+ DBName string `yaml:"db-name" mapstructure:"db-name" json:"db-name"`
35
+ BatchSize uint `yaml:"batch-size" mapstructure:"batch-size" json:"batch-size"`
36
+ Workers uint `yaml:"workers" mapstructure:"workers" json:"workers"`
37
+ Limit uint64 `yaml:"limit" mapstructure:"limit" json:"limit"`
38
+ DoLoad bool `yaml:"do-load" mapstructure:"do-load" json:"do-load"`
39
+ DoCreateDB bool `yaml:"do-create-db" mapstructure:"do-create-db" json:"do-create-db"`
40
+ DoAbortOnExist bool `yaml:"do-abort-on-exist" mapstructure:"do-abort-on-exist" json:"do-abort-on-exist"`
41
+ ReportingPeriod time.Duration `yaml:"reporting-period" mapstructure:"reporting-period" json:"reporting-period"`
42
+ HashWorkers bool `yaml:"hash-workers" mapstructure:"hash-workers" json:"hash-workers"`
43
+ NoFlowControl bool `yaml:"no-flow-control" mapstructure:"no-flow-control" json:"no-flow-control"`
44
+ ChannelCapacity uint `yaml:"channel-capacity" mapstructure:"channel-capacity" json:"channel-capacity"`
45
+ InsertIntervals string `yaml:"insert-intervals" mapstructure:"insert-intervals" json:"insert-intervals"`
46
+ ResultsFile string `yaml:"results-file" mapstructure:"results-file" json:"results-file"`
44
47
// deprecated, should not be used in other places other than tsbs_load_xx commands
45
- FileName string `yaml:"file" mapstructure:"file"`
46
- Seed int64 `yaml:"seed" mapstructure:"seed"`
48
+ FileName string `yaml:"file" mapstructure:"file" json:"file" `
49
+ Seed int64 `yaml:"seed" mapstructure:"seed" json:"seed" `
47
50
}
48
51
49
52
// AddToFlagSet adds command line flags needed by the BenchmarkRunnerConfig to the flag set.
@@ -60,6 +63,7 @@ func (c BenchmarkRunnerConfig) AddToFlagSet(fs *pflag.FlagSet) {
60
63
fs .Int64 ("seed" , 0 , "PRNG seed (default: 0, which uses the current timestamp)" )
61
64
fs .String ("insert-intervals" , "" , "Time to wait between each insert, default '' => all workers insert ASAP. '1,2' = worker 1 waits 1s between inserts, worker 2 and others wait 2s" )
62
65
fs .Bool ("hash-workers" , false , "Whether to consistently hash insert data to the same workers (i.e., the data for a particular host always goes to the same worker)" )
66
+ fs .String ("results-file" , "" , "Write the test results summary json to this file" )
63
67
}
64
68
65
69
type BenchmarkRunner interface {
@@ -138,7 +142,41 @@ func (l *CommonBenchmarkRunner) postRun(wg *sync.WaitGroup, start *time.Time) {
138
142
// Wait for all workers to finish
139
143
wg .Wait ()
140
144
end := time .Now ()
141
- l .summary (end .Sub (* start ))
145
+ took := end .Sub (* start )
146
+ l .summary (took )
147
+ if l .BenchmarkRunnerConfig .ResultsFile != "" {
148
+ metricRate := float64 (l .metricCnt ) / took .Seconds ()
149
+ rowRate := float64 (l .rowCnt ) / took .Seconds ()
150
+ l .saveTestResult (took , * start , end , metricRate , rowRate )
151
+ }
152
+ }
153
+
154
+ func (l * CommonBenchmarkRunner ) saveTestResult (took time.Duration , start time.Time , end time.Time , metricRate , rowRate float64 ) {
155
+ totals := make (map [string ]interface {})
156
+ totals ["metricRate" ] = metricRate
157
+ if l .rowCnt > 0 {
158
+ totals ["rowRate" ] = rowRate
159
+ }
160
+
161
+ testResult := LoaderTestResult {
162
+ ResultFormatVersion : LoaderTestResultVersion ,
163
+ RunnerConfig : l .BenchmarkRunnerConfig ,
164
+ StartTime : start .Unix (),
165
+ EndTime : end .Unix (),
166
+ DurationMillis : took .Milliseconds (),
167
+ Totals : totals ,
168
+ }
169
+
170
+ _ , _ = fmt .Printf ("Saving results json file to %s\n " , l .BenchmarkRunnerConfig .ResultsFile )
171
+ file , err := json .MarshalIndent (testResult , "" , " " )
172
+ if err != nil {
173
+ log .Fatal (err )
174
+ }
175
+
176
+ err = ioutil .WriteFile (l .BenchmarkRunnerConfig .ResultsFile , file , 0644 )
177
+ if err != nil {
178
+ log .Fatal (err )
179
+ }
142
180
}
143
181
144
182
// RunBenchmark takes in a Benchmark b and uses it to run the load benchmark
0 commit comments