From a1261b8b0a38814df453defb2fc2cae3ba0c956a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 17 Feb 2017 10:17:42 -0500 Subject: [PATCH] runtime: do not allocate on every time.Sleep It's common for some goroutines to loop calling time.Sleep. Allocate once per goroutine, not every time. This comes up in runtime/pprof's background reader. Change-Id: I89d17dc7379dca266d2c9cd3aefc2382f5bdbade Reviewed-on: https://go-review.googlesource.com/37162 Reviewed-by: Ian Lance Taylor Reviewed-by: Austin Clements --- src/runtime/proc.go | 1 + src/runtime/runtime2.go | 1 + src/runtime/time.go | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 89244cfa7d..bf1466b9de 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2330,6 +2330,7 @@ func goexit0(gp *g) { gp.waitreason = "" gp.param = nil gp.labels = nil + gp.timer = nil // Note that gp's stack scan is now "valid" because it has no // stack. diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 86176fd2ac..5c05c20d94 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -376,6 +376,7 @@ type g struct { waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order cgoCtxt []uintptr // cgo traceback context labels unsafe.Pointer // profiler labels + timer *timer // cached timer for time.Sleep // Per-G GC state diff --git a/src/runtime/time.go b/src/runtime/time.go index c296338e9b..88ab8b9c02 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -50,7 +50,12 @@ func timeSleep(ns int64) { return } - t := new(timer) + t := getg().timer + if t == nil { + t = new(timer) + getg().timer = t + } + *t = timer{} t.when = nanotime() + ns t.f = goroutineReady t.arg = getg()