Skip to content

Commit bee7014

Browse files
committed
bench/benchprof: support mutex profiles
Release note: None
1 parent db54983 commit bee7014

File tree

2 files changed

+103
-23
lines changed

2 files changed

+103
-23
lines changed

pkg/bench/benchprof/benchprof.go

Lines changed: 102 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,35 @@ import (
2323
type StopFn func(testing.TB)
2424

2525
// Stop stops profiling.
26-
func (f StopFn) Stop(b testing.TB) {
27-
f(b)
26+
func (f StopFn) Stop(tb testing.TB) {
27+
if f != nil {
28+
f(tb)
29+
}
30+
}
31+
32+
// StartAllProfiles starts collection of CPU, heap, and mutex profiles, if the
33+
// "-test.cpuprofile", "-test.memprofile", or "-test.mutexprofile" flags are
34+
// set. See StartCPUProfile, StartMemProfile, and StartMutexProfile for more
35+
// details.
36+
//
37+
// Example usage:
38+
//
39+
// func BenchmarkFoo(b *testing.B) {
40+
// // ..
41+
// b.Run("case", func(b *testing.B) {
42+
// defer benchprof.StartAllProfiles(b).Stop(b)
43+
// // Benchmark loop.
44+
// })
45+
// }
46+
func StartAllProfiles(tb testing.TB) StopFn {
47+
cpuStop := StartCPUProfile(tb)
48+
memStop := StartMemProfile(tb)
49+
mutexStop := StartMutexProfile(tb)
50+
return func(b testing.TB) {
51+
cpuStop(b)
52+
memStop(b)
53+
mutexStop(b)
54+
}
2855
}
2956

3057
// StartCPUProfile starts collection of a CPU profile if the "-test.cpuprofile"
@@ -56,29 +83,25 @@ func StartCPUProfile(tb testing.TB) StopFn {
5683
}
5784
if cpuProfFile == "" {
5885
// Not CPU profile requested.
59-
return func(b testing.TB) {}
86+
return nil
6087
}
6188

6289
prefix := profilePrefix(cpuProfFile)
90+
dir := outputDir(tb)
91+
if dir != "" {
92+
cpuProfFile = filepath.Join(dir, cpuProfFile)
93+
}
6394

6495
// Hijack the harness's profile to make a clean profile.
6596
// The flag is set, so likely a CPU profile started by the Go harness is
6697
// running (unless -count is specified, but StopCPUProfile is idempotent).
6798
runtimepprof.StopCPUProfile()
6899

69-
var outputDir string
70-
if err := sniffarg.DoEnv("test.outputdir", &outputDir); err != nil {
71-
tb.Fatal(err)
72-
}
73-
if outputDir != "" {
74-
cpuProfFile = filepath.Join(outputDir, cpuProfFile)
75-
}
76-
77-
// Remove the harness's profile file to avoid confusion.
100+
// Remove the harness's profile file. It would not be an accurate profile.
78101
_ = os.Remove(cpuProfFile)
79102

80103
// Create a new profile file.
81-
fileName := profileFileName(tb, outputDir, prefix, "cpu")
104+
fileName := profileFileName(tb, dir, prefix, "cpu")
82105
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
83106
if err != nil {
84107
tb.Fatal(err)
@@ -126,25 +149,75 @@ func StartMemProfile(tb testing.TB) StopFn {
126149
}
127150
if memProfFile == "" {
128151
// No heap profile requested.
129-
return func(b testing.TB) {}
152+
return nil
130153
}
131154

132155
prefix := profilePrefix(memProfFile)
156+
dir := outputDir(tb)
157+
if dir != "" {
158+
memProfFile = filepath.Join(dir, memProfFile)
159+
}
133160

134-
var outputDir string
135-
if err := sniffarg.DoEnv("test.outputdir", &outputDir); err != nil {
161+
// Create a new profile file.
162+
fileName := profileFileName(tb, dir, prefix, "mem")
163+
diffAllocs := diffProfile(func() []byte {
164+
p := runtimepprof.Lookup("allocs")
165+
var buf bytes.Buffer
166+
runtime.GC()
167+
if err := p.WriteTo(&buf, 0); err != nil {
168+
tb.Fatal(err)
169+
}
170+
return buf.Bytes()
171+
})
172+
173+
return func(b testing.TB) {
174+
if sl := diffAllocs(b); len(sl) > 0 {
175+
if err := os.WriteFile(fileName, sl, 0644); err != nil {
176+
b.Fatal(err)
177+
}
178+
}
179+
}
180+
}
181+
182+
// StartMutexProfile starts collection of a mutex profile if the
183+
// "-test.cpuprofile" flag has been set. The profile will only collect data
184+
// between calling StartMutexProfile and calling the returned StopFn.
185+
//
186+
// Example usage:
187+
//
188+
// func BenchmarkFoo(b *testing.B) {
189+
// // ..
190+
// b.Run("case", func(b *testing.B) {
191+
// defer benchprof.StartMutexProfile(b).Stop(b)
192+
// // Benchmark loop.
193+
// })
194+
// }
195+
//
196+
// The file name of the profile will include the prefix of the profile flags and
197+
// the benchmark names. For example, "foo_benchmark_thing_1.mutex" would be
198+
// created for a "BenchmarkThing/1" benchmark if the
199+
// "-test.mutexprofile=foo.mutex" flag is set.
200+
func StartMutexProfile(tb testing.TB) StopFn {
201+
var mutexProfFile string
202+
if err := sniffarg.DoEnv("test.mutexprofile", &mutexProfFile); err != nil {
136203
tb.Fatal(err)
137204
}
138-
if outputDir != "" {
139-
memProfFile = filepath.Join(outputDir, memProfFile)
205+
if mutexProfFile == "" {
206+
// No mutex profile requested.
207+
return nil
208+
}
209+
210+
prefix := profilePrefix(mutexProfFile)
211+
dir := outputDir(tb)
212+
if dir != "" {
213+
mutexProfFile = filepath.Join(dir, mutexProfFile)
140214
}
141215

142216
// Create a new profile file.
143-
fileName := profileFileName(tb, outputDir, prefix, "mem")
217+
fileName := profileFileName(tb, dir, prefix, "mutex")
144218
diffAllocs := diffProfile(func() []byte {
145-
p := runtimepprof.Lookup("allocs")
219+
p := runtimepprof.Lookup("mutex")
146220
var buf bytes.Buffer
147-
runtime.GC()
148221
if err := p.WriteTo(&buf, 0); err != nil {
149222
tb.Fatal(err)
150223
}
@@ -193,6 +266,14 @@ func diffProfile(take func() []byte) func(testing.TB) []byte {
193266
}
194267
}
195268

269+
func outputDir(tb testing.TB) string {
270+
var dir string
271+
if err := sniffarg.DoEnv("test.outputdir", &dir); err != nil {
272+
tb.Fatal(err)
273+
}
274+
return dir
275+
}
276+
196277
func profilePrefix(profileArg string) string {
197278
i := strings.Index(profileArg, ".")
198279
if i == -1 {

pkg/bench/tpcc/bench_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ func BenchmarkTPCC(b *testing.B) {
112112

113113
// run executes the TPC-C workload with the specified workload flags.
114114
func run(b *testing.B, ctx context.Context, pgURLs [nodes]string, workloadFlags []string) {
115-
defer benchprof.StartCPUProfile(b).Stop(b)
116-
defer benchprof.StartMemProfile(b).Stop(b)
115+
defer benchprof.StartAllProfiles(b).Stop(b)
117116

118117
flags := append([]string{
119118
"--wait=0",

0 commit comments

Comments
 (0)