From 045b8fb5e6ddfdbba91f1cddeab6eeb839fefd33 Mon Sep 17 00:00:00 2001 From: Milind Chabbi Date: Wed, 21 Apr 2021 00:00:37 -0700 Subject: [PATCH] runtime/pprof: include example uses of pprof with PMU. Add four examples loop fusion, matrix transpose, concurrent gorotuines, and a weighted serial execution of functions to demonstrate profiling use cases with different metrics. --- src/net/http/pprof/examples/fusion.go | 61 +++++++ src/net/http/pprof/examples/goroutine.go | 190 ++++++++++++++++++++ src/net/http/pprof/examples/run.sh | 28 +++ src/net/http/pprof/examples/serial.go | 135 +++++++++++++++ src/net/http/pprof/examples/transpose.go | 58 +++++++ src/runtime/pprof/examples/fusion.go | 82 +++++++++ src/runtime/pprof/examples/goroutine.go | 211 +++++++++++++++++++++++ src/runtime/pprof/examples/run.sh | 13 ++ src/runtime/pprof/examples/serial.go | 154 +++++++++++++++++ src/runtime/pprof/examples/transpose.go | 89 ++++++++++ 10 files changed, 1021 insertions(+) create mode 100644 src/net/http/pprof/examples/fusion.go create mode 100644 src/net/http/pprof/examples/goroutine.go create mode 100644 src/net/http/pprof/examples/run.sh create mode 100644 src/net/http/pprof/examples/serial.go create mode 100644 src/net/http/pprof/examples/transpose.go create mode 100644 src/runtime/pprof/examples/fusion.go create mode 100644 src/runtime/pprof/examples/goroutine.go create mode 100644 src/runtime/pprof/examples/run.sh create mode 100644 src/runtime/pprof/examples/serial.go create mode 100644 src/runtime/pprof/examples/transpose.go diff --git a/src/net/http/pprof/examples/fusion.go b/src/net/http/pprof/examples/fusion.go new file mode 100644 index 0000000000000..c6167a1b375de --- /dev/null +++ b/src/net/http/pprof/examples/fusion.go @@ -0,0 +1,61 @@ +// +build ignore + +package main + +import ( + "log" + _ "math/rand" + "net/http" + _ "net/http/pprof" +) + +const N = (1 << 20) + +var a []float32 +var b []float32 +var c []float32 +var d []float32 + +func init() { + a = make([]float32, N) + b = make([]float32, N) + c = make([]float32, N) + d = make([]float32, N) + // for i := 0; i < N; i++ { + // a[i] = rand.Float32() + // b[i] = rand.Float32() + // } +} + +//go:noinline +func addSub() { + for i := 0; i < N; i++ { + c[i] = b[i] + c[i] + } + for i := 0; i < N; i++ { + d[i] = b[i] - c[i] + } +} + +//go:noinline +func addSubFuse() { + for i := 0; i < N; i++ { + c[i] = b[i] + c[i] + d[i] = b[i] - c[i] + } +} + +func run() error { + addSub() + addSubFuse() + return nil +} + +func main() { + go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() + for { + if err := run(); err != nil { + log.Fatal(err) + } + } +} diff --git a/src/net/http/pprof/examples/goroutine.go b/src/net/http/pprof/examples/goroutine.go new file mode 100644 index 0000000000000..7c58f85324543 --- /dev/null +++ b/src/net/http/pprof/examples/goroutine.go @@ -0,0 +1,190 @@ +// +build ignore + +package main + +import ( + "log" + "net/http" + _ "net/http/pprof" + "sync" +) + +var wg sync.WaitGroup + +//go:noinline +func f1() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f2() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f3() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f4() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f5() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f6() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f7() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f8() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f9() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f10() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func run() error { + wg.Add(10) + defer wg.Wait() + + go f1() + go f2() + go f3() + go f4() + go f5() + go f6() + go f7() + go f8() + go f9() + go f10() + + return nil +} + +func main() { + go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() + for { + if err := run(); err != nil { + log.Fatal(err) + } + } +} diff --git a/src/net/http/pprof/examples/run.sh b/src/net/http/pprof/examples/run.sh new file mode 100644 index 0000000000000..320ea5d35315b --- /dev/null +++ b/src/net/http/pprof/examples/run.sh @@ -0,0 +1,28 @@ +set -ex +#GOROOT= +#PATH= +#if needed and supported +#GO_PPROF_PRECISION=3 + +HOST=localhost +PORT=6060 +L1MISS="r08d1" + +for f in fusion.go goroutine.go serial.go transpose.go +do +name=`basename $f .go` +go run $f & +pid=$! +sleep 2 +# simple timer profile +curl -o ${name}.timer.prof ${HOST}:${PORT}/debug/pprof/profile?seconds=10 +# CPU cycles @ 10M +curl -o ${name}.cycles.prof ${HOST}:${PORT}/debug/pprof/profile?event=cycles\&period=10000000\&seconds=20 +# CPU instructions @ 1M +curl -o ${name}.ins.prof ${HOST}:${PORT}/debug/pprof/profile?event=instructions\&period=1000000\&seconds=20 +# CPU L1 D-cache miss @ 10000 +curl -o ${name}.l1miss.prof ${HOST}:${PORT}/debug/pprof/profile?event=${L1MISS}\&period=10000\&seconds=20 +# CPU LLC cache miss @ 10000 +curl -o ${name}.llcmiss.prof ${HOST}:${PORT}/debug/pprof/profile?event=cacheMisses\&period=10000\&seconds=20 +killall $name || "cannot kill" +done diff --git a/src/net/http/pprof/examples/serial.go b/src/net/http/pprof/examples/serial.go new file mode 100644 index 0000000000000..f815790d81ff0 --- /dev/null +++ b/src/net/http/pprof/examples/serial.go @@ -0,0 +1,135 @@ +// +build ignore + +package main + +import ( + "flag" + "fmt" + "log" + "net/http" + _ "net/http/pprof" +) + +//go:noinline +func J_expect_18_18(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func I_expect_16_36(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func H_expect_14_546(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func G_expect_12_73(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func F_expect_10_91(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func E_expect_9_09(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func D_expect_7_27(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func C_expect_5_46(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func B_expect_3_64(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func A_expect_1_82(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +func main() { + go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() + + var q uint64 + multiplier := flag.Uint64("m", 100000, "multiplier") + flag.Parse() + fmt.Println("multiplier=", *multiplier) + mult := *multiplier + + for i := uint64(0); ; i++ { + f := i + A_expect_1_82(0xebabefac23, 1*mult) + g := i + B_expect_3_64(f, 2*mult) + h := i + C_expect_5_46(g, 3*mult) + k := i + D_expect_7_27(h, 4*mult) + l := i + E_expect_9_09(k, 5*mult) + m := i + F_expect_10_91(l, 6*mult) + n := i + G_expect_12_73(m, 7*mult) + o := i + H_expect_14_546(n, 8*mult) + p := i + I_expect_16_36(o, 9*mult) + q = i + J_expect_18_18(p, 10*mult) + } + fmt.Println(q) +} diff --git a/src/net/http/pprof/examples/transpose.go b/src/net/http/pprof/examples/transpose.go new file mode 100644 index 0000000000000..23dd175386ec7 --- /dev/null +++ b/src/net/http/pprof/examples/transpose.go @@ -0,0 +1,58 @@ +// +build ignore + +package main + +import ( + "log" + _ "math/rand" + "net/http" + _ "net/http/pprof" +) + +const N = 16000 + +var a [N][N]float32 + +//go:noinline +func transposeTiled() { + BS := 100 + for ii := 0; ii < N; ii += BS { + for jj := 0; jj < N; jj += BS { + for i := ii; i < ii+BS; i++ { + for j := jj; j < jj+BS; j++ { + v1 := a[i][j] + v2 := a[j][i] + a[i][j] = v2 + a[j][i] = v1 + } + } + } + } +} + +//go:noinline +func transpose() { + for i := 0; i < N; i++ { + for j := 0; j < N; j++ { + v1 := a[i][j] + v2 := a[j][i] + a[i][j] = v2 + a[j][i] = v1 + } + } +} + +func run() error { + transpose() + transposeTiled() + return nil +} + +func main() { + go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() + for { + if err := run(); err != nil { + log.Fatal(err) + } + } +} diff --git a/src/runtime/pprof/examples/fusion.go b/src/runtime/pprof/examples/fusion.go new file mode 100644 index 0000000000000..e747d6bc04eea --- /dev/null +++ b/src/runtime/pprof/examples/fusion.go @@ -0,0 +1,82 @@ +// +build ignore + +package main + +import ( + "log" + "math/rand" + "os" + "runtime/pprof" +) + +const N = (1 << 20) + +var a []float32 +var b []float32 +var c []float32 +var d []float32 + +func init() { + a = make([]float32, N) + b = make([]float32, N) + c = make([]float32, N) + d = make([]float32, N) + for i := 0; i < N; i++ { + a[i] = rand.Float32() + b[i] = rand.Float32() + } +} + +//go:noinline +func addSub() { + for i := 0; i < N; i++ { + c[i] = b[i] + c[i] + } + for i := 0; i < N; i++ { + d[i] = b[i] - c[i] + } +} + +//go:noinline +func addSubFuse() { + for i := 0; i < N; i++ { + c[i] = b[i] + c[i] + d[i] = b[i] - c[i] + } +} + +func run() error { + addSub() + addSubFuse() + return nil +} + +func main() { + cwd, _ := os.Getwd() + prefix := cwd + "/" + os.Args[0] + cycleFile, err := os.Create(prefix + ".cycle.prof") + if err != nil { + log.Fatal(err) + } + defer cycleFile.Close() + cacheRefFile, err := os.Create(prefix + ".cacheRef.prof") + if err != nil { + log.Fatal(err) + } + defer cacheRefFile.Close() + cacheMissFile, err := os.Create(prefix + ".cacheMiss.prof") + if err != nil { + log.Fatal(err) + } + defer cacheMissFile.Close() + + if err := pprof.StartCPUProfileWithConfig(pprof.CPUCycles(cycleFile, 10000000), pprof.CPUCacheReferences(cacheRefFile, 10000), pprof.CPUCacheMisses(cacheMissFile, 10000)); err != nil { + log.Fatal(err) + } + defer pprof.StopCPUProfile() + for i := 0; i < 100; i++ { + if err := run(); err != nil { + log.Fatal(err) + } + } +} diff --git a/src/runtime/pprof/examples/goroutine.go b/src/runtime/pprof/examples/goroutine.go new file mode 100644 index 0000000000000..00490d31e57bf --- /dev/null +++ b/src/runtime/pprof/examples/goroutine.go @@ -0,0 +1,211 @@ +// +build ignore + +package main + +import ( + "log" + "os" + "runtime/pprof" + "sync" +) + +var wg sync.WaitGroup + +//go:noinline +func f1() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f2() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f3() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f4() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f5() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f6() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f7() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f8() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f9() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +//go:noinline +func f10() int { + defer wg.Done() + + var sum int + for i := 0; i < 500000000; i++ { + sum -= i / 2 + sum *= i + sum /= i/3 + 1 + sum -= i / 4 + } + + return sum +} + +func run() error { + wg.Add(10) + defer wg.Wait() + + go f1() + go f2() + go f3() + go f4() + go f5() + go f6() + go f7() + go f8() + go f9() + go f10() + + return nil +} + +func main() { + cwd, _ := os.Getwd() + prefix := cwd + "/" + os.Args[0] + cycleFile, err := os.Create(prefix + ".cycle.prof") + if err != nil { + log.Fatal(err) + } + defer cycleFile.Close() + cacheRefFile, err := os.Create(prefix + ".cacheRef.prof") + if err != nil { + log.Fatal(err) + } + defer cacheRefFile.Close() + cacheMissFile, err := os.Create(prefix + ".cacheMiss.prof") + if err != nil { + log.Fatal(err) + } + defer cacheMissFile.Close() + + if err := pprof.StartCPUProfileWithConfig(pprof.CPUCycles(cycleFile, 10000000), pprof.CPUCacheReferences(cacheRefFile, 10000), pprof.CPUCacheMisses(cacheMissFile, 10000)); err != nil { + log.Fatal(err) + } + defer pprof.StopCPUProfile() + for i := 0; i < 1; i++ { + if err := run(); err != nil { + log.Fatal(err) + } + } + +} diff --git a/src/runtime/pprof/examples/run.sh b/src/runtime/pprof/examples/run.sh new file mode 100644 index 0000000000000..938c02a5c9d08 --- /dev/null +++ b/src/runtime/pprof/examples/run.sh @@ -0,0 +1,13 @@ +set -ex +#GOROOT= +#PATH= +#if needed and supported +#GO_PPROF_PRECISION=3 +export GO_PPROF_ENABLE_MULTIPLE_CPU_PROFILES=true + +for f in fusion.go goroutine.go serial.go transpose.go +do +name=`basename $f .go` +go build $f +./${name} +done diff --git a/src/runtime/pprof/examples/serial.go b/src/runtime/pprof/examples/serial.go new file mode 100644 index 0000000000000..6053aadf7e302 --- /dev/null +++ b/src/runtime/pprof/examples/serial.go @@ -0,0 +1,154 @@ +// +build ignore + +package main + +import ( + "flag" + "fmt" + "log" + "os" + "runtime/pprof" +) + +//go:noinline +func J_expect_18_18(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func I_expect_16_36(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func H_expect_14_546(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func G_expect_12_73(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func F_expect_10_91(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func E_expect_9_09(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func D_expect_7_27(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func C_expect_5_46(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func B_expect_3_64(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +//go:noinline +func A_expect_1_82(v uint64, trip uint64) uint64 { + ret := v + for i := trip; i > 0; i-- { + ret += i + ret = ret ^ (i + 0xcafebabe) + } + return ret +} + +func main() { + var q uint64 + multiplier := flag.Uint64("m", 100000, "multiplier") + flag.Parse() + fmt.Println("multiplier=", *multiplier) + mult := *multiplier + cwd, _ := os.Getwd() + prefix := cwd + "/" + os.Args[0] + cycleFile, err := os.Create(prefix + ".cycle.prof") + if err != nil { + log.Fatal(err) + } + defer cycleFile.Close() + cacheRefFile, err := os.Create(prefix + ".cacheRef.prof") + if err != nil { + log.Fatal(err) + } + defer cacheRefFile.Close() + cacheMissFile, err := os.Create(prefix + ".cacheMiss.prof") + if err != nil { + log.Fatal(err) + } + defer cacheMissFile.Close() + + if err := pprof.StartCPUProfileWithConfig(pprof.CPUCycles(cycleFile, 10000000), pprof.CPUCacheReferences(cacheRefFile, 10000), pprof.CPUCacheMisses(cacheMissFile, 10000)); err != nil { + log.Fatal(err) + } + defer pprof.StopCPUProfile() + for i := uint64(0); i < uint64(1000); i++ { + f := i + A_expect_1_82(0xebabefac23, 1*mult) + g := i + B_expect_3_64(f, 2*mult) + h := i + C_expect_5_46(g, 3*mult) + k := i + D_expect_7_27(h, 4*mult) + l := i + E_expect_9_09(k, 5*mult) + m := i + F_expect_10_91(l, 6*mult) + n := i + G_expect_12_73(m, 7*mult) + o := i + H_expect_14_546(n, 8*mult) + p := i + I_expect_16_36(o, 9*mult) + q = i + J_expect_18_18(p, 10*mult) + } + fmt.Println(q) +} diff --git a/src/runtime/pprof/examples/transpose.go b/src/runtime/pprof/examples/transpose.go new file mode 100644 index 0000000000000..e66f6405075d9 --- /dev/null +++ b/src/runtime/pprof/examples/transpose.go @@ -0,0 +1,89 @@ +// +build ignore + +package main + +import ( + "log" + "math/rand" + "os" + "runtime/pprof" +) + +const N = 16000 + +var a [N][N]float32 + +func init() { + return + for i := 0; i < N; i++ { + for j := 0; j < N; j++ { + a[i][j] = rand.Float32() + } + } +} + +//go:noinline +func transposeTiled() { + BS := 100 + for ii := 0; ii < N; ii += BS { + for jj := 0; jj < N; jj += BS { + for i := ii; i < ii+BS; i++ { + for j := jj; j < jj+BS; j++ { + v1 := a[i][j] + v2 := a[j][i] + a[i][j] = v2 + a[j][i] = v1 + } + } + } + } +} + +//go:noinline +func transpose() { + for i := 0; i < N; i++ { + for j := 0; j < N; j++ { + v1 := a[i][j] + v2 := a[j][i] + a[i][j] = v2 + a[j][i] = v1 + } + } +} + +func run() error { + transpose() + transposeTiled() + return nil +} + +func main() { + cwd, _ := os.Getwd() + prefix := cwd + "/" + os.Args[0] + cycleFile, err := os.Create(prefix + ".cycle.prof") + if err != nil { + log.Fatal(err) + } + defer cycleFile.Close() + cacheRefFile, err := os.Create(prefix + ".cacheRef.prof") + if err != nil { + log.Fatal(err) + } + defer cacheRefFile.Close() + cacheMissFile, err := os.Create(prefix + ".cacheMiss.prof") + if err != nil { + log.Fatal(err) + } + defer cacheMissFile.Close() + + if err := pprof.StartCPUProfileWithConfig(pprof.CPUCycles(cycleFile, 10000000), pprof.CPUCacheReferences(cacheRefFile, 10000), pprof.CPUCacheMisses(cacheMissFile, 10000)); err != nil { + log.Fatal(err) + } + defer pprof.StopCPUProfile() + for i := 0; i < 1; i++ { + if err := run(); err != nil { + log.Fatal(err) + } + } + +}