Source file src/context/benchmark_test.go

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     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  	// Generate concurrent contexts.
    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