From 0b9c1ad20d4d4120e30f05129987f44de57032be Mon Sep 17 00:00:00 2001 From: Keegan Carruthers-Smith Date: Sun, 15 Apr 2018 22:22:13 +0100 Subject: [PATCH] context: avoid defer in the cancelCtx.Err method MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta CheckCanceled/Err-4 53.5ns ± 2% 20.8ns ± 0% -61.05% (p=0.008 n=5+5) CheckCanceled/Done-4 44.4ns ± 1% 44.5ns ± 0% ~ (p=0.889 n=5+5) Change-Id: I2c68700a2b33f8feb3d307ce7c966590a3e960af Reviewed-on: https://go-review.googlesource.com/107137 Reviewed-by: Brad Fitzpatrick --- src/context/benchmark_test.go | 18 ++++++++++++++++++ src/context/context.go | 5 +++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/context/benchmark_test.go b/src/context/benchmark_test.go index 3c526dd106..6dd8510ff4 100644 --- a/src/context/benchmark_test.go +++ b/src/context/benchmark_test.go @@ -96,3 +96,21 @@ func buildContextTree(root Context, depth int) { 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: + } + } + }) +} diff --git a/src/context/context.go b/src/context/context.go index 06580e0465..1b4fa41b8c 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -334,8 +334,9 @@ func (c *cancelCtx) Done() <-chan struct{} { func (c *cancelCtx) Err() error { c.mu.Lock() - defer c.mu.Unlock() - return c.err + err := c.err + c.mu.Unlock() + return err } func (c *cancelCtx) String() string { -- 2.50.0