mirror of
https://github.com/golang/go
synced 2024-10-01 01:18:32 -06:00
runtime/pprof: speed up CPU profiling shutdown
The core CPU profiling loop contains a 100ms sleep. This is important to reduce overhead. However, it means that it takes 200ms to shutting down a program with CPU profiling enabled. When trying to collect many samples by running a short-lived program many times, this adds up. This change cuts the shutdown penalty in half by skipping the sleep whenever possible. Change-Id: Ic3177f8e1a2d331fe1a1ecd7c8c06f50beb42535 Reviewed-on: https://go-review.googlesource.com/c/go/+/228886 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
parent
12d1c9b863
commit
1f0738c157
@ -81,6 +81,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
"unsafe"
|
||||
@ -714,10 +715,22 @@ func (p runtimeProfile) Stack(i int) []uintptr { return p[i].Stack() }
|
||||
|
||||
var cpu struct {
|
||||
sync.Mutex
|
||||
profiling bool
|
||||
profiling uint32 // bool, accessed atomically
|
||||
done chan bool
|
||||
}
|
||||
|
||||
func cpuProfiling() bool {
|
||||
return atomic.LoadUint32(&cpu.profiling) != 0
|
||||
}
|
||||
|
||||
func setCPUProfiling(b bool) {
|
||||
if b {
|
||||
atomic.StoreUint32(&cpu.profiling, 1)
|
||||
} else {
|
||||
atomic.StoreUint32(&cpu.profiling, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// StartCPUProfile enables CPU profiling for the current process.
|
||||
// While profiling, the profile will be buffered and written to w.
|
||||
// StartCPUProfile returns an error if profiling is already enabled.
|
||||
@ -747,10 +760,10 @@ func StartCPUProfile(w io.Writer) error {
|
||||
cpu.done = make(chan bool)
|
||||
}
|
||||
// Double-check.
|
||||
if cpu.profiling {
|
||||
if cpuProfiling() {
|
||||
return fmt.Errorf("cpu profiling already in use")
|
||||
}
|
||||
cpu.profiling = true
|
||||
setCPUProfiling(true)
|
||||
runtime.SetCPUProfileRate(hz)
|
||||
go profileWriter(w)
|
||||
return nil
|
||||
@ -767,7 +780,9 @@ func profileWriter(w io.Writer) {
|
||||
b := newProfileBuilder(w)
|
||||
var err error
|
||||
for {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
if cpuProfiling() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
data, tags, eof := readProfile()
|
||||
if e := b.addCPUData(data, tags); e != nil && err == nil {
|
||||
err = e
|
||||
@ -792,10 +807,10 @@ func StopCPUProfile() {
|
||||
cpu.Lock()
|
||||
defer cpu.Unlock()
|
||||
|
||||
if !cpu.profiling {
|
||||
if !cpuProfiling() {
|
||||
return
|
||||
}
|
||||
cpu.profiling = false
|
||||
setCPUProfiling(false)
|
||||
runtime.SetCPUProfileRate(0)
|
||||
<-cpu.done
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user