[go] context: implement Context.Value using iteration rather than recursion

247 views
Skip to first unread message

Richard Oudkerk (Gerrit)

unread,
Jul 19, 2021, 4:38:44 PM7/19/21
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Richard Oudkerk has uploaded this change for review.

View Change

context: implement Context.Value using iteration rather than recursion

In profiles of a production server, 2.3% of CPU time is spent in
runtime.newstack for stacks with 12 or more chained Context.Value
calls. Using iteration will avoid some needless stack resizes.

When calling Context.Value in the same goroutine (see
DeepValueSameGoRoutine), no stack resizing is needed (after warming
up), and this change reduces time/op by around 10%.

The time to start a new goroutine and call Context.Value (see
DeepValueNewGoRoutine) is reduced by over 75% if a stack resize is
needed. If you factor out the overhead of starting the goroutine
(about 960ns) then, avoiding the stack resize saves about 95%.

name old time/op new time/op delta
CommonParentCancel-12 960ns ± 1% 958ns ± 1% ~ (p=0.561 n=9+9)
WithTimeout/concurrency=40-12 1.31µs ± 2% 1.29µs ± 6% ~ (p=0.305 n=9+10)
WithTimeout/concurrency=4000-12 1.30µs ± 2% 1.30µs ± 2% ~ (p=0.343 n=10+10)
WithTimeout/concurrency=400000-12 1.03µs ± 1% 1.02µs ± 2% ~ (p=0.213 n=9+9)
CancelTree/depth=1/Root=Background-12 123ns ± 5% 126ns ± 2% +2.61% (p=0.023 n=10+9)
CancelTree/depth=1/Root=OpenCanceler-12 781ns ± 4% 806ns ± 4% +3.20% (p=0.022 n=9+10)
CancelTree/depth=1/Root=ClosedCanceler-12 370ns ± 4% 369ns ± 3% ~ (p=0.497 n=9+10)
CancelTree/depth=10/Root=Background-12 4.74µs ± 4% 4.78µs ± 3% ~ (p=0.516 n=10+10)
CancelTree/depth=10/Root=OpenCanceler-12 6.31µs ± 4% 6.29µs ± 4% ~ (p=1.000 n=10+10)
CancelTree/depth=10/Root=ClosedCanceler-12 2.10µs ± 5% 2.09µs ± 5% ~ (p=0.839 n=10+10)
CancelTree/depth=100/Root=Background-12 51.0µs ± 3% 51.2µs ± 2% ~ (p=0.631 n=10+10)
CancelTree/depth=100/Root=OpenCanceler-12 60.8µs ± 1% 61.6µs ± 4% ~ (p=0.274 n=8+10)
CancelTree/depth=100/Root=ClosedCanceler-12 19.3µs ± 2% 19.0µs ± 3% ~ (p=0.123 n=10+10)
CancelTree/depth=1000/Root=Background-12 504µs ± 4% 512µs ± 4% ~ (p=0.123 n=10+10)
CancelTree/depth=1000/Root=OpenCanceler-12 615µs ± 6% 619µs ± 4% ~ (p=1.000 n=10+10)
CancelTree/depth=1000/Root=ClosedCanceler-12 190µs ± 2% 192µs ± 3% ~ (p=0.190 n=9+9)
CheckCanceled/Err-12 12.1ns ± 2% 12.1ns ± 2% ~ (p=0.615 n=10+10)
CheckCanceled/Done-12 7.27ns ± 1% 7.26ns ± 1% ~ (p=0.698 n=10+10)
ContextCancelDone-12 1.03ns ± 1% 1.03ns ± 1% ~ (p=0.474 n=9+9)
DeepValueNewGoRoutine/depth=10-12 1.02µs ± 3% 0.99µs ± 2% -3.41% (p=0.000 n=10+10)
DeepValueNewGoRoutine/depth=20-12 1.11µs ± 3% 1.08µs ± 2% -2.51% (p=0.004 n=10+10)
DeepValueNewGoRoutine/depth=30-12 5.55µs ±10% 1.17µs ± 4% -78.91% (p=0.000 n=10+10)
DeepValueNewGoRoutine/depth=50-12 5.70µs ±13% 1.35µs ± 2% -76.31% (p=0.000 n=10+10)
DeepValueNewGoRoutine/depth=100-12 9.69µs ± 4% 1.82µs ± 2% -81.18% (p=0.000 n=10+10)
DeepValueSameGoRoutine/depth=10-12 54.2ns ± 2% 46.8ns ± 2% -13.71% (p=0.000 n=9+9)
DeepValueSameGoRoutine/depth=20-12 109ns ± 2% 97ns ± 2% -11.11% (p=0.000 n=10+10)
DeepValueSameGoRoutine/depth=30-12 155ns ± 3% 140ns ± 1% -9.49% (p=0.000 n=10+10)
DeepValueSameGoRoutine/depth=50-12 256ns ± 2% 226ns ± 2% -11.83% (p=0.000 n=10+10)
DeepValueSameGoRoutine/depth=100-12 492ns ± 3% 442ns ± 1% -10.15% (p=0.000 n=10+10)

Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
---
M src/context/context.go
1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/context/context.go b/src/context/context.go
index 733c5f5..57de5eb 100644
--- a/src/context/context.go
+++ b/src/context/context.go
@@ -352,7 +352,7 @@
if key == &cancelCtxKey {
return c
}
- return c.Context.Value(key)
+ return value(c.Context, key)
}

func (c *cancelCtx) Done() <-chan struct{} {
@@ -563,5 +563,31 @@
if c.key == key {
return c.val
}
- return c.Context.Value(key)
+ return value(c.Context, key)
+}
+
+func value(ctx Context, key interface{}) interface{} {
+ for {
+ switch tCtx := ctx.(type) {
+ case *valueCtx:
+ if key == tCtx.key {
+ return tCtx.val
+ }
+ ctx = tCtx.Context
+ case *cancelCtx:
+ if key == &cancelCtxKey {
+ return (*cancelCtx)(tCtx) // Redundant cast to confirm underlying type.
+ }
+ ctx = tCtx.Context
+ case *timerCtx:
+ if key == &cancelCtxKey {
+ return (*cancelCtx)(&tCtx.cancelCtx) // Redundant cast to confirm underlying type.
+ }
+ ctx = tCtx.Context
+ case *emptyCtx:
+ return nil
+ default:
+ return ctx.Value(key)
+ }
+ }
}

To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
Gerrit-Change-Number: 335790
Gerrit-PatchSet: 1
Gerrit-Owner: Richard Oudkerk <roud...@google.com>
Gerrit-MessageType: newchange

Richard Oudkerk (Gerrit)

unread,
Jul 19, 2021, 4:51:44 PM7/19/21
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Richard Oudkerk uploaded patch set #2 to this change.

View Change

Fixes #47292


Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
---
M src/context/context.go
1 file changed, 28 insertions(+), 2 deletions(-)

To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
Gerrit-Change-Number: 335790
Gerrit-PatchSet: 2
Gerrit-Owner: Richard Oudkerk <roud...@google.com>
Gerrit-MessageType: newpatchset

Ian Lance Taylor (Gerrit)

unread,
Jul 19, 2021, 5:07:52 PM7/19/21
to Richard Oudkerk, goph...@pubsubhelper.golang.org, Damien Neil, Sameer Ajmani, Go Bot, golang-co...@googlegroups.com

Attention is currently required from: Richard Oudkerk, Damien Neil, Sameer Ajmani.

Patch set 2:Run-TryBot +1

View Change

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 2
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-CC: Go Bot <go...@golang.org>
    Gerrit-Attention: Richard Oudkerk <roud...@google.com>
    Gerrit-Attention: Damien Neil <dn...@google.com>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-Comment-Date: Mon, 19 Jul 2021 21:07:46 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    Gerrit-MessageType: comment

    Rob Pike (Gerrit)

    unread,
    Jul 19, 2021, 6:22:55 PM7/19/21
    to Richard Oudkerk, goph...@pubsubhelper.golang.org, Rob Pike, Go Bot, Ian Lance Taylor, Damien Neil, Sameer Ajmani, golang-co...@googlegroups.com

    Attention is currently required from: Richard Oudkerk, Damien Neil, Sameer Ajmani.

    Patch set 2:Code-Review -1

    View Change

    1 comment:

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 2
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Go Bot <go...@golang.org>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Rob Pike <r...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-Attention: Richard Oudkerk <roud...@google.com>
    Gerrit-Attention: Damien Neil <dn...@google.com>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-Comment-Date: Mon, 19 Jul 2021 22:22:48 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    Gerrit-MessageType: comment

    Damien Neil (Gerrit)

    unread,
    Aug 5, 2021, 1:53:00 PM8/5/21
    to Richard Oudkerk, goph...@pubsubhelper.golang.org, Rob Pike, Go Bot, Ian Lance Taylor, Sameer Ajmani, golang-co...@googlegroups.com

    Attention is currently required from: Rob Pike, Sameer Ajmani.

    Patch set 2:Run-TryBot +1Code-Review +1Trust +1

    View Change

    1 comment:

    • Patchset:

      • Patch Set #2:

        Are you still -1 on this, Rob?

        I agree that we don't want to avoid recursion in general, but I think the iterative approach is reasonable in this case.

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 2
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Go Bot <go...@golang.org>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Rob Pike <r...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-Attention: Rob Pike <r...@golang.org>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-Comment-Date: Thu, 05 Aug 2021 17:52:56 +0000

    Rob Pike (Gerrit)

    unread,
    Aug 30, 2021, 9:12:09 PM8/30/21
    to Richard Oudkerk, goph...@pubsubhelper.golang.org, Damien Neil, Rob Pike, Go Bot, Ian Lance Taylor, Sameer Ajmani, golang-co...@googlegroups.com

    Attention is currently required from: Rob Pike, Sameer Ajmani.

    Rob Pike removed a vote from this change.

    View Change

    Removed Code-Review-1 by Rob Pike <r...@golang.org>

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 2
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Go Bot <go...@golang.org>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Rob Pike <r...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-Attention: Rob Pike <r...@golang.org>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-MessageType: deleteVote

    Ian Lance Taylor (Gerrit)

    unread,
    Sep 30, 2021, 6:15:08 PM9/30/21
    to Richard Oudkerk, goph...@pubsubhelper.golang.org, Damien Neil, Rob Pike, Go Bot, Sameer Ajmani, golang-co...@googlegroups.com

    Attention is currently required from: Richard Oudkerk, Rob Pike, Sameer Ajmani.

    View Change

    4 comments:

    • File src/context/context.go:

      • Patch Set #2, Line 569: func value(ctx Context, key interface{}) interface{} {

        In this file variables of type Context appear to be named c. I know that's not the convention in other packages, but it seems that we should do the same here.

      • Patch Set #2, Line 571: switch tCtx := ctx.(type) {

        In this kind of type switch it's routine to write

            switch ctx := ctx.(type)

        or given the above comment
            switch c := c.(type)

        and then only refer to ctx below. This ensures that there is no possible confusion between the general ctx and the type-specific one.

      • Patch Set #2, Line 579: return (*cancelCtx)(tCtx) // Redundant cast to confirm underlying type.

        This type conversion is truly redundant. The type switch ensures that the type of tCtx here is *cancelCtx. I think we should remove the type conversion and the comment.

      • Patch Set #2, Line 584: return (*cancelCtx)(&tCtx.cancelCtx) // Redundant cast to confirm underlying type.

        Here again the type conversion is not needed.

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 2
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Go Bot <go...@golang.org>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Rob Pike <r...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-Attention: Richard Oudkerk <roud...@google.com>
    Gerrit-Attention: Rob Pike <r...@golang.org>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-Comment-Date: Thu, 30 Sep 2021 22:15:02 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Richard Oudkerk (Gerrit)

    unread,
    Oct 1, 2021, 5:16:44 AM10/1/21
    to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

    Attention is currently required from: Richard Oudkerk, Rob Pike, Sameer Ajmani.

    Richard Oudkerk uploaded patch set #3 to this change.

    View Change

    context: implement Context.Value using iteration rather than recursion

    In profiles of a production server, 2.3% of CPU time is spent in
    runtime.newstack for stacks with 12 or more chained Context.Value
    calls. Using iteration will avoid some needless stack resizes.

    When calling Context.Value in the same goroutine (see
    DeepValueSameGoRoutine) , no stack resizing is needed (after warming
    M src/context/benchmark_test.go
    2 files changed, 121 insertions(+), 2 deletions(-)

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 3
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Go Bot <go...@golang.org>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Rob Pike <r...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-Attention: Richard Oudkerk <roud...@google.com>
    Gerrit-Attention: Rob Pike <r...@golang.org>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-MessageType: newpatchset

    Richard Oudkerk (Gerrit)

    unread,
    Oct 1, 2021, 5:20:29 AM10/1/21
    to goph...@pubsubhelper.golang.org, Damien Neil, Rob Pike, Go Bot, Ian Lance Taylor, Sameer Ajmani, golang-co...@googlegroups.com

    Attention is currently required from: Ian Lance Taylor, Rob Pike, Sameer Ajmani.

    View Change

    5 comments:

      • In this file variables of type Context appear to be named c. […]

        Done

      • In this kind of type switch it's routine to write […]

        On lines 576, 581, 586 we need to update the ctx variable. But we can't if we shadow it inside the switch.

        I have renamed the function parameter to c and the switch variable to ctx.

      • This type conversion is truly redundant. […]

        Done

      • Patch Set #2, Line 584: return (*cancelCtx)(&tCtx.cancelCtx) // Redundant cast to confirm underlying type.

        Here again the type conversion is not needed.

      • Done

    To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
    Gerrit-Change-Number: 335790
    Gerrit-PatchSet: 3
    Gerrit-Owner: Richard Oudkerk <roud...@google.com>
    Gerrit-Reviewer: Damien Neil <dn...@google.com>
    Gerrit-Reviewer: Go Bot <go...@golang.org>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Rob Pike <r...@golang.org>
    Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
    Gerrit-Attention: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Attention: Rob Pike <r...@golang.org>
    Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
    Gerrit-Comment-Date: Fri, 01 Oct 2021 09:20:21 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Ian Lance Taylor <ia...@golang.org>
    Gerrit-MessageType: comment

    Ian Lance Taylor (Gerrit)

    unread,
    Oct 1, 2021, 8:22:12 PM10/1/21
    to Richard Oudkerk, goph...@pubsubhelper.golang.org, Damien Neil, Rob Pike, Go Bot, Sameer Ajmani, golang-co...@googlegroups.com

    Attention is currently required from: Richard Oudkerk, Rob Pike, Sameer Ajmani.

    Patch set 3:Run-TryBot +1

    View Change

      To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
      Gerrit-Change-Number: 335790
      Gerrit-PatchSet: 3
      Gerrit-Owner: Richard Oudkerk <roud...@google.com>
      Gerrit-Reviewer: Damien Neil <dn...@google.com>
      Gerrit-Reviewer: Go Bot <go...@golang.org>
      Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
      Gerrit-Reviewer: Rob Pike <r...@golang.org>
      Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
      Gerrit-Attention: Richard Oudkerk <roud...@google.com>
      Gerrit-Attention: Rob Pike <r...@golang.org>
      Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
      Gerrit-Comment-Date: Sat, 02 Oct 2021 00:22:08 +0000

      Ian Lance Taylor (Gerrit)

      unread,
      Oct 1, 2021, 8:44:19 PM10/1/21
      to Richard Oudkerk, goph...@pubsubhelper.golang.org, Go Bot, Damien Neil, Rob Pike, Sameer Ajmani, golang-co...@googlegroups.com

      Attention is currently required from: Richard Oudkerk, Rob Pike, Sameer Ajmani.

      Patch set 3:Code-Review +2

      View Change

      1 comment:

      To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
      Gerrit-Change-Number: 335790
      Gerrit-PatchSet: 3
      Gerrit-Owner: Richard Oudkerk <roud...@google.com>
      Gerrit-Reviewer: Damien Neil <dn...@google.com>
      Gerrit-Reviewer: Go Bot <go...@golang.org>
      Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
      Gerrit-Reviewer: Rob Pike <r...@golang.org>
      Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
      Gerrit-Attention: Richard Oudkerk <roud...@google.com>
      Gerrit-Attention: Rob Pike <r...@golang.org>
      Gerrit-Attention: Sameer Ajmani <sam...@golang.org>
      Gerrit-Comment-Date: Sat, 02 Oct 2021 00:44:14 +0000

      Ian Lance Taylor (Gerrit)

      unread,
      Oct 1, 2021, 8:44:28 PM10/1/21
      to Richard Oudkerk, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Go Bot, Damien Neil, Rob Pike, Sameer Ajmani, golang-co...@googlegroups.com

      Ian Lance Taylor submitted this change.

      View Change


      Approvals: Ian Lance Taylor: Looks good to me, approved; Run TryBots Damien Neil: Trusted Go Bot: TryBots succeeded
      Reviewed-on: https://go-review.googlesource.com/c/go/+/335790
      Run-TryBot: Ian Lance Taylor <ia...@golang.org>
      TryBot-Result: Go Bot <go...@golang.org>
      Reviewed-by: Ian Lance Taylor <ia...@golang.org>
      Trust: Damien Neil <dn...@google.com>

      ---
      M src/context/context.go
      M src/context/benchmark_test.go
      2 files changed, 126 insertions(+), 2 deletions(-)

      diff --git a/src/context/benchmark_test.go b/src/context/benchmark_test.go
      index 69d75ff..144f473 100644
      --- a/src/context/benchmark_test.go
      +++ b/src/context/benchmark_test.go
      @@ -152,3 +152,39 @@
      }
      })
      }
      +
      +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)
      + }
      + })
      + }
      +}
      diff --git a/src/context/context.go b/src/context/context.go
      index 733c5f5..a9e1470 100644

      --- a/src/context/context.go
      +++ b/src/context/context.go
      @@ -352,7 +352,7 @@
      if key == &cancelCtxKey {
      return c
      }
      - return c.Context.Value(key)
      + return value(c.Context, key)
      }

      func (c *cancelCtx) Done() <-chan struct{} {
      @@ -563,5 +563,31 @@
      if c.key == key {
      return c.val
      }
      - return c.Context.Value(key)
      + return value(c.Context, key)
      +}
      +
      +func value(c Context, key interface{}) interface{} {
      + for {
      + switch ctx := c.(type) {
      + case *valueCtx:
      + if key == ctx.key {
      + return ctx.val
      + }
      + c = ctx.Context

      + case *cancelCtx:
      + if key == &cancelCtxKey {
      +				return c
      + }
      + c = ctx.Context

      + case *timerCtx:
      + if key == &cancelCtxKey {
      +				return &ctx.cancelCtx
      + }
      + c = ctx.Context

      + case *emptyCtx:
      + return nil
      + default:
      +			return c.Value(key)
      + }
      + }
      }

      To view, visit change 335790. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75
      Gerrit-Change-Number: 335790
      Gerrit-PatchSet: 4
      Gerrit-Owner: Richard Oudkerk <roud...@google.com>
      Gerrit-Reviewer: Damien Neil <dn...@google.com>
      Gerrit-Reviewer: Go Bot <go...@golang.org>
      Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
      Gerrit-Reviewer: Rob Pike <r...@golang.org>
      Gerrit-Reviewer: Sameer Ajmani <sam...@golang.org>
      Gerrit-MessageType: merged
      Reply all
      Reply to author
      Forward
      0 new messages