[go] runtime: skip printlock when output goes to a goroutine buffer

0 views
Skip to first unread message

Gopher Robot (Gerrit)

unread,
Aug 10, 2026, 5:03:43 PM (13 hours ago) Aug 10
to David Teather, Gerrit Bot, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Dmitri Shuralyov, Dmitri Shuralyov, Keith Randall, Keith Randall, golang...@luci-project-accounts.iam.gserviceaccount.com, Austin Clements, Michael Knyszek, Michael Pratt, Emmanuel Odeke, Ian Lance Taylor, golang-co...@googlegroups.com

Gopher Robot submitted the change

Change information

Commit message:
runtime: skip printlock when output goes to a goroutine buffer

runtime.Stack prints its traceback through the print* machinery, which
takes printlock, which acquires the process-global debuglock. Stack
diverts its output into the calling goroutine's own writebuf, so the
lock protects nothing and concurrent callers serialize for no reason.

Return early from printlock and printunlock when gp.writebuf is non-nil
and the M is not dying. writebuf is non-nil only for runtime.Stack and a
few runtime tests, so ordinary print output still takes the lock. The
dying check is needed because gwrite ignores writebuf once the M is
dying and writes to stderr, which is shared.

Also move recordForPanic in gwrite below the writebuf check. It takes
printlock itself and mutates the global printBacklog, so two concurrent
Stack calls would otherwise race on it, invisibly to the race detector
since runtime packages are built NoInstrument. Stack output therefore no
longer reaches printBacklog. A traceback is larger than the 512-byte
buffer, so debug.Stack from recovery middleware was already overwriting
the print output leading up to a crash.

Traceback, panic and fatal error output are unchanged. Three benchmarks
and three tests are added, one of which fails if the recordForPanic move
is dropped.

goos: darwin
goarch: arm64
pkg: runtime
cpu: Apple M2 Pro
│ old │ new │
│ sec/op │ sec/op vs base │
Stack-10 1140.5n ± 1% 709.3n ± 1% -37.81% (p=0.000 n=20)
StackParallel-10 1689.5n ± 3% 110.1n ± 2% -93.48% (p=0.000 n=20)
StackAll-10 64.72µ ± 7% 54.71µ ± 1% -15.46% (p=0.000 n=20)
geomean 4.996µ 1.623µ -67.52%

StackParallel used to get slower as procs were added, 936n at one up to
1682n at eight. It now runs 631n down to 109n. B/op and allocs/op are
unchanged.

Fixes #56400
Change-Id: I21e20cdab5971d2c9f62dfd0a03909c9463e1de6
GitHub-Last-Rev: 576943ce779a2cf42a299879295878f4813b629a
GitHub-Pull-Request: golang/go#80807
Reviewed-by: Keith Randall <k...@golang.org>
Auto-Submit: Keith Randall <k...@golang.org>
Reviewed-by: Keith Randall <k...@google.com>
Reviewed-by: Dmitri Shuralyov <dmit...@google.com>
Files:
  • M src/runtime/export_test.go
  • M src/runtime/print.go
  • M src/runtime/print_test.go
Change size: M
Delta: 3 files changed, 143 insertions(+), 3 deletions(-)
Branch: refs/heads/master
Submit Requirements:
Open in Gerrit
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: merged
Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I21e20cdab5971d2c9f62dfd0a03909c9463e1de6
Gerrit-Change-Number: 812600
Gerrit-PatchSet: 2
Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
Gerrit-Reviewer: Austin Clements <aus...@google.com>
Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
Gerrit-Reviewer: Emmanuel Odeke <emma...@orijtech.com>
Gerrit-Reviewer: Gopher Robot <go...@golang.org>
Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
Gerrit-Reviewer: Keith Randall <k...@golang.org>
Gerrit-Reviewer: Keith Randall <k...@google.com>
Gerrit-Reviewer: Michael Knyszek <mkny...@google.com>
Gerrit-Reviewer: Michael Pratt <mpr...@google.com>
Gerrit-CC: David Teather <contact.da...@gmail.com>
Gerrit-CC: Dmitri Shuralyov <dmit...@golang.org>
open
diffy
satisfied_requirement
Reply all
Reply to author
Forward
0 new messages