Skip to content

Commit e465745

Browse files
committed
bench/tpcc: remove --profile flag
The `--profile` flag is no longer supported. Instead, CPU and heap profiles will be collected if `-test.cpuprofile` or `-test.memprofile` are provided. The benchmark will "hijack" the standard profiles and create new profiles that omit CPU samples and allocations made during the setup phase of the benchmark. The profile names will include the prefix of the profile flags and the benchmark names. For example, the profiles "foo_tpcc_literal_new_order.cpu" and "foo_tpcc_literal_new_order.mem" will be created when running the benchmark: ./dev bench pkg/bench/tpcc -f BenchmarkTPCC/literal/new_order \ --test-args '-test.cpuprofile=foo.cpu -test.memprofile=foo.mem' Note that the "foo.cpu" file will not be created because we must stop the global CPU profiler in order to collect profiles that omit setup samples. The "foo.mem" file will created and include all allocations made during the entire duration of the benchmark. Release note: None
1 parent 8c760de commit e465745

File tree

1 file changed

+72
-28
lines changed

1 file changed

+72
-28
lines changed

pkg/bench/tpcc/bench_test.go

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"bytes"
1010
"context"
1111
gosql "database/sql"
12-
"flag"
1312
"fmt"
1413
"io"
1514
"os"
@@ -44,25 +43,28 @@ const (
4443
nodes = 3
4544
)
4645

47-
var profileFlag = flag.String("profile", "",
48-
"if set, CPU and heap profiles are collected with the given file name prefix")
49-
5046
// BenchmarkTPCC runs TPC-C transactions against a single warehouse. Both the
5147
// optimized and literal implementations of our TPC-C workload are benchmarked.
5248
// There are benchmarks for running each transaction individually, as well as a
5349
// "default" mix that runs the standard mix of TPC-C transactions.
5450
//
55-
// CPU and heap profiles can be collected by passing the "-profile" flag with a
56-
// prefix for the profile file names. The profile names will include the
57-
// benchmark names, e.g., "foo_tpcc_literal_new_order.cpu" and
58-
// "foo_tpcc_literal_new_order.mem" will be created when running the benchmark:
51+
// If CPU or heap profiles are requested with the "-test.cpuprofile" or
52+
// "-test.memprofile" flags, the benchmark will "hijack" the standard profiles
53+
// and create new profiles that omit CPU samples and allocations made during the
54+
// setup phase of the benchmark.
55+
//
56+
// The profile names will include the prefix of the profile flags and the
57+
// benchmark names. For example, the profiles "foo_tpcc_literal_new_order.cpu"
58+
// and "foo_tpcc_literal_new_order.mem" will be created when running the
59+
// benchmark:
5960
//
6061
// ./dev bench pkg/bench/tpcc -f BenchmarkTPCC/literal/new_order \
61-
// --test-args '-test.benchtime=30s -profile=foo'
62+
// --test-args '-test.cpuprofile=foo.cpu -test.memprofile=foo.mem'
6263
//
63-
// These profiles will omit CPU samples and allocations made during the setup
64-
// phase of the benchmark, unlike profiles collected with the "-test.cpuprofile"
65-
// and "-test.memprofile" flags.
64+
// NB: The "foo.cpu" file will not be created because we must stop the global
65+
// CPU profiler in order to collect profiles that omit setup samples. The
66+
// "foo.mem" file will created and include all allocations made during the
67+
// entire duration of the benchmark.
6668
func BenchmarkTPCC(b *testing.B) {
6769
defer log.Scope(b).Close(b)
6870

@@ -237,17 +239,41 @@ func (f doneFn) Stop(b testing.TB) {
237239
}
238240

239241
func startCPUProfile(b testing.TB) doneFn {
240-
prefix := *profileFlag
241-
if prefix == "" {
242+
var cpuProfFile string
243+
if err := sniffarg.DoEnv("test.cpuprofile", &cpuProfFile); err != nil {
244+
b.Fatal(err)
245+
}
246+
if cpuProfFile == "" {
247+
// Not CPU profile requested.
242248
return func(b testing.TB) {}
243249
}
244250

245-
fileName := profileFileName(b, prefix, "cpu")
251+
prefix := profilePrefix(cpuProfFile)
252+
253+
// Hijack the harness's profile to make a clean profile.
254+
// The flag is set, so likely a CPU profile started by the Go harness is
255+
// running (unless -count is specified, but StopCPUProfile is idempotent).
256+
runtimepprof.StopCPUProfile()
257+
258+
var outputDir string
259+
if err := sniffarg.DoEnv("test.outputdir", &outputDir); err != nil {
260+
b.Fatal(err)
261+
}
262+
if outputDir != "" {
263+
cpuProfFile = filepath.Join(outputDir, cpuProfFile)
264+
}
265+
266+
// Remove the harness's profile file to avoid confusion.
267+
_ = os.Remove(cpuProfFile)
268+
269+
// Create a new profile file.
270+
fileName := profileFileName(b, outputDir, prefix, "cpu")
246271
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
247272
if err != nil {
248273
b.Fatal(err)
249274
}
250275

276+
// Start profiling.
251277
if err := runtimepprof.StartCPUProfile(f); err != nil {
252278
b.Fatal(err)
253279
}
@@ -261,12 +287,27 @@ func startCPUProfile(b testing.TB) doneFn {
261287
}
262288

263289
func startAllocsProfile(b testing.TB) doneFn {
264-
prefix := *profileFlag
265-
if prefix == "" {
290+
var memProfFile string
291+
if err := sniffarg.DoEnv("test.memprofile", &memProfFile); err != nil {
292+
b.Fatal(err)
293+
}
294+
if memProfFile == "" {
295+
// No heap profile requested.
266296
return func(b testing.TB) {}
267297
}
268298

269-
fileName := profileFileName(b, prefix, "mem")
299+
prefix := profilePrefix(memProfFile)
300+
301+
var outputDir string
302+
if err := sniffarg.DoEnv("test.outputdir", &outputDir); err != nil {
303+
b.Fatal(err)
304+
}
305+
if outputDir != "" {
306+
memProfFile = filepath.Join(outputDir, memProfFile)
307+
}
308+
309+
// Create a new profile file.
310+
fileName := profileFileName(b, outputDir, prefix, "mem")
270311
diffAllocs := diffProfile(b, func() []byte {
271312
p := runtimepprof.Lookup("allocs")
272313
var buf bytes.Buffer
@@ -295,13 +336,13 @@ func diffProfile(b testing.TB, take func() []byte) func(testing.TB) []byte {
295336
if baseBytes == nil {
296337
return func(tb testing.TB) []byte { return nil }
297338
}
298-
pBase, err := profile.ParseData(baseBytes)
299-
if err != nil {
300-
b.Fatal(err)
301-
}
302-
303339
return func(b testing.TB) []byte {
304-
pNew, err := profile.ParseData(take())
340+
newBytes := take()
341+
pBase, err := profile.ParseData(baseBytes)
342+
if err != nil {
343+
b.Fatal(err)
344+
}
345+
pNew, err := profile.ParseData(newBytes)
305346
if err != nil {
306347
b.Fatal(err)
307348
}
@@ -321,12 +362,15 @@ func diffProfile(b testing.TB, take func() []byte) func(testing.TB) []byte {
321362
}
322363
}
323364

324-
func profileFileName(b testing.TB, prefix, suffix string) string {
325-
var outputDir string
326-
if err := sniffarg.DoEnv("test.outputdir", &outputDir); err != nil {
327-
b.Fatal(err)
365+
func profilePrefix(profileArg string) string {
366+
i := strings.Index(profileArg, ".")
367+
if i == -1 {
368+
return profileArg
328369
}
370+
return profileArg[:i]
371+
}
329372

373+
func profileFileName(b testing.TB, outputDir, prefix, suffix string) string {
330374
saniRE := regexp.MustCompile(`\W+`)
331375
testName := strings.TrimPrefix(b.Name(), "Benchmark")
332376
testName = strings.ToLower(testName)

0 commit comments

Comments
 (0)