Source file
src/context/benchmark_test.go
1
2
3
4
5 package context_test
6
7 import (
8 . "context"
9 "fmt"
10 "runtime"
11 "sync"
12 "testing"
13 "time"
14 )
15
16 func BenchmarkCommonParentCancel(b *testing.B) {
17 root := WithValue(Background(), "key", "value")
18 shared, sharedcancel := WithCancel(root)
19 defer sharedcancel()
20
21 b.ResetTimer()
22 b.RunParallel(func(pb *testing.PB) {
23 x := 0
24 for pb.Next() {
25 ctx, cancel := WithCancel(shared)
26 if ctx.Value("key").(string) != "value" {
27 b.Fatal("should not be reached")
28 }
29 for i := 0; i < 100; i++ {
30 x /= x + 1
31 }
32 cancel()
33 for i := 0; i < 100; i++ {
34 x /= x + 1
35 }
36 }
37 })
38 }
39
40 func BenchmarkWithTimeout(b *testing.B) {
41 for concurrency := 40; concurrency <= 4e5; concurrency *= 100 {
42 name := fmt.Sprintf("concurrency=%d", concurrency)
43 b.Run(name, func(b *testing.B) {
44 benchmarkWithTimeout(b, concurrency)
45 })
46 }
47 }
48
49 func benchmarkWithTimeout(b *testing.B, concurrentContexts int) {
50 gomaxprocs := runtime.GOMAXPROCS(0)
51 perPContexts := concurrentContexts / gomaxprocs
52 root := Background()
53
54
55 var wg sync.WaitGroup
56 ccf := make([][]CancelFunc, gomaxprocs)
57 for i := range ccf {
58 wg.Add(1)
59 go func(i int) {
60 defer wg.Done()
61 cf := make([]CancelFunc, perPContexts)
62 for j := range cf {
63 _, cf[j] = WithTimeout(root, time.Hour)
64 }
65 ccf[i] = cf
66 }(i)
67 }
68 wg.Wait()
69
70 b.ResetTimer()
71 b.RunParallel(func(pb *testing.PB) {
72 wcf := make([]CancelFunc, 10)
73 for pb.Next() {
74 for i := range wcf {
75 _, wcf[i] = WithTimeout(root, time.Hour)
76 }
77 for _, f := range wcf {
78 f()
79 }
80 }
81 })
82 b.StopTimer()
83
84 for _, cf := range ccf {
85 for _, f := range cf {
86 f()
87 }
88 }
89 }
90
91 func BenchmarkCancelTree(b *testing.B) {
92 depths := []int{1, 10, 100, 1000}
93 for _, d := range depths {
94 b.Run(fmt.Sprintf("depth=%d", d), func(b *testing.B) {
95 b.Run("Root=Background", func(b *testing.B) {
96 for i := 0; i < b.N; i++ {
97 buildContextTree(Background(), d)
98 }
99 })
100 b.Run("Root=OpenCanceler", func(b *testing.B) {
101 for i := 0; i < b.N; i++ {
102 ctx, cancel := WithCancel(Background())
103 buildContextTree(ctx, d)
104 cancel()
105 }
106 })
107 b.Run("Root=ClosedCanceler", func(b *testing.B) {
108 for i := 0; i < b.N; i++ {
109 ctx, cancel := WithCancel(Background())
110 cancel()
111 buildContextTree(ctx, d)
112 }
113 })
114 })
115 }
116 }
117
118 func buildContextTree(root Context, depth int) {
119 for d := 0; d < depth; d++ {
120 root, _ = WithCancel(root)
121 }
122 }
123
124 func BenchmarkCheckCanceled(b *testing.B) {
125 ctx, cancel := WithCancel(Background())
126 cancel()
127 b.Run("Err", func(b *testing.B) {
128 for i := 0; i < b.N; i++ {
129 ctx.Err()
130 }
131 })
132 b.Run("Done", func(b *testing.B) {
133 for i := 0; i < b.N; i++ {
134 select {
135 case <-ctx.Done():
136 default:
137 }
138 }
139 })
140 }
141
142 func BenchmarkContextCancelDone(b *testing.B) {
143 ctx, cancel := WithCancel(Background())
144 defer cancel()
145
146 b.RunParallel(func(pb *testing.PB) {
147 for pb.Next() {
148 select {
149 case <-ctx.Done():
150 default:
151 }
152 }
153 })
154 }
155
156 func BenchmarkDeepValueNewGoRoutine(b *testing.B) {
157 for _, depth := range []int{10, 20, 30, 50, 100} {
158 ctx := Background()
159 for i := 0; i < depth; i++ {
160 ctx = WithValue(ctx, i, i)
161 }
162
163 b.Run(fmt.Sprintf("depth=%d", depth), func(b *testing.B) {
164 for i := 0; i < b.N; i++ {
165 var wg sync.WaitGroup
166 wg.Add(1)
167 go func() {
168 defer wg.Done()
169 ctx.Value(-1)
170 }()
171 wg.Wait()
172 }
173 })
174 }
175 }
176
177 func BenchmarkDeepValueSameGoRoutine(b *testing.B) {
178 for _, depth := range []int{10, 20, 30, 50, 100} {
179 ctx := Background()
180 for i := 0; i < depth; i++ {
181 ctx = WithValue(ctx, i, i)
182 }
183
184 b.Run(fmt.Sprintf("depth=%d", depth), func(b *testing.B) {
185 for i := 0; i < b.N; i++ {
186 ctx.Value(-1)
187 }
188 })
189 }
190 }
191
View as plain text