summaryrefslogtreecommitdiffstats
path: root/src/context/benchmark_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/context/benchmark_test.go')
-rw-r--r--src/context/benchmark_test.go190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/context/benchmark_test.go b/src/context/benchmark_test.go
new file mode 100644
index 0000000..144f473
--- /dev/null
+++ b/src/context/benchmark_test.go
@@ -0,0 +1,190 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context_test
+
+import (
+ . "context"
+ "fmt"
+ "runtime"
+ "sync"
+ "testing"
+ "time"
+)
+
+func BenchmarkCommonParentCancel(b *testing.B) {
+ root := WithValue(Background(), "key", "value")
+ shared, sharedcancel := WithCancel(root)
+ defer sharedcancel()
+
+ b.ResetTimer()
+ b.RunParallel(func(pb *testing.PB) {
+ x := 0
+ for pb.Next() {
+ ctx, cancel := WithCancel(shared)
+ if ctx.Value("key").(string) != "value" {
+ b.Fatal("should not be reached")
+ }
+ for i := 0; i < 100; i++ {
+ x /= x + 1
+ }
+ cancel()
+ for i := 0; i < 100; i++ {
+ x /= x + 1
+ }
+ }
+ })
+}
+
+func BenchmarkWithTimeout(b *testing.B) {
+ for concurrency := 40; concurrency <= 4e5; concurrency *= 100 {
+ name := fmt.Sprintf("concurrency=%d", concurrency)
+ b.Run(name, func(b *testing.B) {
+ benchmarkWithTimeout(b, concurrency)
+ })
+ }
+}
+
+func benchmarkWithTimeout(b *testing.B, concurrentContexts int) {
+ gomaxprocs := runtime.GOMAXPROCS(0)
+ perPContexts := concurrentContexts / gomaxprocs
+ root := Background()
+
+ // Generate concurrent contexts.
+ var wg sync.WaitGroup
+ ccf := make([][]CancelFunc, gomaxprocs)
+ for i := range ccf {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+ cf := make([]CancelFunc, perPContexts)
+ for j := range cf {
+ _, cf[j] = WithTimeout(root, time.Hour)
+ }
+ ccf[i] = cf
+ }(i)
+ }
+ wg.Wait()
+
+ b.ResetTimer()
+ b.RunParallel(func(pb *testing.PB) {
+ wcf := make([]CancelFunc, 10)
+ for pb.Next() {
+ for i := range wcf {
+ _, wcf[i] = WithTimeout(root, time.Hour)
+ }
+ for _, f := range wcf {
+ f()
+ }
+ }
+ })
+ b.StopTimer()
+
+ for _, cf := range ccf {
+ for _, f := range cf {
+ f()
+ }
+ }
+}
+
+func BenchmarkCancelTree(b *testing.B) {
+ depths := []int{1, 10, 100, 1000}
+ for _, d := range depths {
+ b.Run(fmt.Sprintf("depth=%d", d), func(b *testing.B) {
+ b.Run("Root=Background", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ buildContextTree(Background(), d)
+ }
+ })
+ b.Run("Root=OpenCanceler", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ctx, cancel := WithCancel(Background())
+ buildContextTree(ctx, d)
+ cancel()
+ }
+ })
+ b.Run("Root=ClosedCanceler", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ctx, cancel := WithCancel(Background())
+ cancel()
+ buildContextTree(ctx, d)
+ }
+ })
+ })
+ }
+}
+
+func buildContextTree(root Context, depth int) {
+ for d := 0; d < depth; d++ {
+ root, _ = WithCancel(root)
+ }
+}
+
+func BenchmarkCheckCanceled(b *testing.B) {
+ ctx, cancel := WithCancel(Background())
+ cancel()
+ b.Run("Err", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ctx.Err()
+ }
+ })
+ b.Run("Done", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ select {
+ case <-ctx.Done():
+ default:
+ }
+ }
+ })
+}
+
+func BenchmarkContextCancelDone(b *testing.B) {
+ ctx, cancel := WithCancel(Background())
+ defer cancel()
+
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ select {
+ case <-ctx.Done():
+ default:
+ }
+ }
+ })
+}
+
+func BenchmarkDeepValueNewGoRoutine(b *testing.B) {
+ for _, depth := range []int{10, 20, 30, 50, 100} {
+ ctx := Background()
+ for i := 0; i < depth; i++ {
+ ctx = WithValue(ctx, i, i)
+ }
+
+ b.Run(fmt.Sprintf("depth=%d", depth), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ ctx.Value(-1)
+ }()
+ wg.Wait()
+ }
+ })
+ }
+}
+
+func BenchmarkDeepValueSameGoRoutine(b *testing.B) {
+ for _, depth := range []int{10, 20, 30, 50, 100} {
+ ctx := Background()
+ for i := 0; i < depth; i++ {
+ ctx = WithValue(ctx, i, i)
+ }
+
+ b.Run(fmt.Sprintf("depth=%d", depth), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ctx.Value(-1)
+ }
+ })
+ }
+}