Skip to content

Commit

Permalink
runtime: increase profiling stack depth to 128
Browse files Browse the repository at this point in the history
The current stack depth limit for alloc, mutex, block, threadcreate and
goroutine profiles of 32 frequently leads to truncated stack traces in
production applications. Increase the limit to 128 which is the same
size used by the execution tracer.

Create internal/profilerecord to define variants of the runtime's
StackRecord, MemProfileRecord and BlockProfileRecord types that can hold
arbitrarily big stack traces. Implement internal profiling APIs based on
these new types and use them for creating protobuf profiles and to act
as shims for the public profiling APIs using the old types.

This will lead to an increase in memory usage for applications that
use the impacted profile types and have stack traces exceeding the
current limit of 32. Those applications will also experience a slight
increase in CPU usage, but this will hopefully soon be mitigated via CL
540476 and 533258 which introduce frame pointer unwinding for the
relevant profile types.

For #43669.

Change-Id: Ie53762e65d0f6295f5d4c7d3c87172d5a052164e
Reviewed-on: https://go-review.googlesource.com/c/go/+/572396
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Austin Clements <[email protected]>
Reviewed-by: Cherry Mui <[email protected]>
  • Loading branch information
felixge authored and aclements committed May 21, 2024
1 parent 47187a4 commit 1b9dc3e
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 110 deletions.
2 changes: 2 additions & 0 deletions doc/next/6-stdlib/99-minor/runtime/pprof/43669.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The maximum stack depth for alloc, mutex, block, threadcreate and goroutine
profiles has been raised from 32 to 128 frames.
1 change: 1 addition & 0 deletions src/cmd/internal/objabi/pkgspecial.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ var runtimePkgs = []string{
"internal/godebugs",
"internal/goexperiment",
"internal/goos",
"internal/profilerecord",
"internal/stringslite",
}

Expand Down
5 changes: 3 additions & 2 deletions src/go/build/deps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var depsRules = `
internal/goarch, internal/godebugs,
internal/goexperiment, internal/goos, internal/byteorder,
internal/goversion, internal/nettrace, internal/platform,
internal/trace/traceviewer/format,
internal/profilerecord, internal/trace/traceviewer/format,
log/internal,
unicode/utf8, unicode/utf16, unicode,
unsafe;
Expand All @@ -65,7 +65,8 @@ var depsRules = `
internal/goarch,
internal/godebugs,
internal/goexperiment,
internal/goos
internal/goos,
internal/profilerecord
< internal/bytealg
< internal/stringslite
< internal/itoa
Expand Down
28 changes: 28 additions & 0 deletions src/internal/profilerecord/profilerecord.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package profilerecord holds internal types used to represent profiling
// records with deep stack traces.
//
// TODO: Consider moving this to internal/runtime, see golang.org/issue/65355.
package profilerecord

type StackRecord struct {
Stack []uintptr
}

type MemProfileRecord struct {
AllocBytes, FreeBytes int64
AllocObjects, FreeObjects int64
Stack []uintptr
}

func (r *MemProfileRecord) InUseBytes() int64 { return r.AllocBytes - r.FreeBytes }
func (r *MemProfileRecord) InUseObjects() int64 { return r.AllocObjects - r.FreeObjects }

type BlockProfileRecord struct {
Count int64
Cycles int64
Stack []uintptr
}
4 changes: 2 additions & 2 deletions src/runtime/cpuprof.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ func CPUProfile() []byte {
panic("CPUProfile no longer available")
}

//go:linkname runtime_pprof_runtime_cyclesPerSecond runtime/pprof.runtime_cyclesPerSecond
func runtime_pprof_runtime_cyclesPerSecond() int64 {
//go:linkname pprof_cyclesPerSecond
func pprof_cyclesPerSecond() int64 {
return ticksPerSecond()
}

Expand Down
Loading

0 comments on commit 1b9dc3e

Please sign in to comment.