From e103051eda12ba70a72a5d24dced61705589ba2b Mon Sep 17 00:00:00 2001 From: Yonder Blue Date: Wed, 19 Oct 2022 08:23:32 -0400 Subject: [PATCH] Add clock (fgprof) profile --- go.mod | 2 ++ profile.go | 21 +++++++++++++++++++++ profile_test.go | 16 ++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/go.mod b/go.mod index 08932f3..6dd15d7 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/pkg/profile go 1.13 + +require github.com/felixge/fgprof v0.9.3 diff --git a/profile.go b/profile.go index ec66e30..ea4e853 100644 --- a/profile.go +++ b/profile.go @@ -12,6 +12,8 @@ import ( "runtime/pprof" "runtime/trace" "sync/atomic" + + "github.com/felixge/fgprof" ) const ( @@ -22,6 +24,7 @@ const ( traceMode threadCreateMode goroutineMode + clockMode ) // Profile represents an active profiling session. @@ -122,6 +125,10 @@ func ThreadcreationProfile(p *Profile) { p.mode = threadCreateMode } // It disables any previous profiling settings. func GoroutineProfile(p *Profile) { p.mode = goroutineMode } +// ClockProfile enables wall clock (fgprof) profiling. +// It disables any previous profiling settings. +func ClockProfile(p *Profile) { p.mode = clockMode } + // ProfilePath controls the base path where various profiling // files are written. If blank, the base path will be generated // by ioutil.TempDir. @@ -287,6 +294,20 @@ func Start(options ...func(*Profile)) interface { f.Close() logf("profile: goroutine profiling disabled, %s", fn) } + + case clockMode: + fn := filepath.Join(path, "clock.pprof") + f, err := os.Create(fn) + if err != nil { + log.Fatalf("profile: could not create clock profile %q: %v", fn, err) + } + logf("profile: clock profiling enabled, %s", fn) + stop := fgprof.Start(f, fgprof.FormatPprof) + prof.closer = func() { + stop() + f.Close() + logf("profile: clock profiling disabled, %s", fn) + } } if !prof.noShutdownHook { diff --git a/profile_test.go b/profile_test.go index e33012c..b4cd651 100644 --- a/profile_test.go +++ b/profile_test.go @@ -122,6 +122,22 @@ func main() { Stderr("profile: mutex profiling enabled"), NoErr, }, + }, { + name: "clock profile", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.ClockProfile).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: clock profiling enabled"), + NoErr, + }, }, { name: "profile path", code: `