1
2
3
4
5
6
7
8
9 package main
10
11 import (
12 "bytes"
13 "context"
14 "fmt"
15 "internal/profile"
16 "log"
17 "os"
18 "runtime"
19 "runtime/pprof"
20 "runtime/trace"
21 "strings"
22 "time"
23 )
24
25 func main() {
26 cpuBuf := new(bytes.Buffer)
27 if err := pprof.StartCPUProfile(cpuBuf); err != nil {
28 log.Fatalf("failed to start CPU profile: %v", err)
29 }
30
31 if err := trace.Start(os.Stdout); err != nil {
32 log.Fatalf("failed to start tracing: %v", err)
33 }
34
35 dur := 100 * time.Millisecond
36 func() {
37
38
39
40
41 ctx := context.Background()
42 defer trace.StartRegion(ctx, "cpuHogger").End()
43 pprof.Do(ctx, pprof.Labels("tracing", "on"), func(ctx context.Context) {
44 cpuHogger(cpuHog1, &salt1, dur)
45 })
46
47
48
49 cpuHogger(cpuHog1, &salt1, dur)
50 }()
51
52 trace.Stop()
53 pprof.StopCPUProfile()
54
55
56
57 prof, err := profile.Parse(cpuBuf)
58 if err != nil {
59 log.Fatalf("failed to parse CPU profile: %v", err)
60 }
61
62
63
64
65 pprofStacks := make(map[string]int)
66 for _, s := range prof.Sample {
67 if s.Label["tracing"] != nil {
68 var fns []string
69 var leaf string
70 for _, loc := range s.Location {
71 for _, line := range loc.Line {
72 fns = append(fns, fmt.Sprintf("%s:%d", line.Function.Name, line.Line))
73 leaf = line.Function.Name
74 }
75 }
76
77
78
79
80
81
82
83
84 switch leaf {
85 case "runtime._System", "runtime._GC", "runtime._ExternalCode", "runtime._VDSO":
86 continue
87 }
88 stack := strings.Join(fns, "|")
89 samples := int(s.Value[0])
90 pprofStacks[stack] += samples
91 }
92 }
93 for stack, samples := range pprofStacks {
94 fmt.Fprintf(os.Stderr, "%s\t%d\n", stack, samples)
95 }
96 }
97
98 func cpuHogger(f func(x int) int, y *int, dur time.Duration) {
99
100
101
102
103
104 t0 := time.Now()
105 accum := *y
106 for i := 0; i < 500 || time.Since(t0) < dur; i++ {
107 accum = f(accum)
108 }
109 *y = accum
110 }
111
112 var (
113 salt1 = 0
114 )
115
116
117
118
119 func cpuHog1(x int) int {
120 return cpuHog0(x, 1e5)
121 }
122
123 func cpuHog0(x, n int) int {
124 foo := x
125 for i := 0; i < n; i++ {
126 if i%1000 == 0 {
127
128 runtime.Gosched()
129 }
130 if foo > 0 {
131 foo *= foo
132 } else {
133 foo *= foo + 1
134 }
135 }
136 return foo
137 }
138
View as plain text