| | |
| | |
| | |
| |
|
| | 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() |
| |
|
| | |
| | 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) |
| | } |
| | }) |
| | } |
| | } |
| |
|
| | func BenchmarkErrOK(b *testing.B) { |
| | ctx, cancel := WithCancel(Background()) |
| | defer cancel() |
| | for b.Loop() { |
| | if err := ctx.Err(); err != nil { |
| | b.Fatalf("ctx.Err() = %v", err) |
| | } |
| | } |
| | } |
| |
|
| | func BenchmarkErrCanceled(b *testing.B) { |
| | ctx, cancel := WithCancel(Background()) |
| | cancel() |
| | for b.Loop() { |
| | if err := ctx.Err(); err == nil { |
| | b.Fatalf("ctx.Err() = %v", err) |
| | } |
| | } |
| | } |
| |
|