A profile is a set of stack traces, showing the order of calls that led to an event. For example, memory allocation. Packages can create and maintain their own profiles. The most common reason is to monitor any resources that require explicit closure: files, network connections.
var libProfile *pprof.Profile func init() { profName := "my_experiment_thing" libProfile = pprof.Lookup(profName) if libProfile == nil { libProfile = pprof.NewProfile(profName) } }
// Warning: /vendor panic possibilities var panicProfile = pprof.NewProfile("this_unique_name")
type someResource struct { *os.File } func MustResource() *someResource { f, err := os.Create(...) if err != nil { panic(err) } r := &someResource{f} libProfile.Add(r, 1) return r } func (r *someResource) Close() error { libProfile.Remove(r) return r.File.Close() }
func usesAResource() { pprofKey := new(byte) libProfile.Add(pprofKey, 1) defer libProfile.Remove(pprofKey) // .... }
import _ "net/http/pprof"
httpMux.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
package main import ( "fmt" "log" "net/http" _ "net/http/pprof" "os" "runtime/pprof" "sync/atomic" "time" ) var libProfile *pprof.Profile func init() { profName := "my_experiment_thing" libProfile = pprof.Lookup(profName) if libProfile == nil { libProfile = pprof.NewProfile(profName) } } type someResource struct { *os.File } var fileIndex = int64(0) func MustResource() *someResource { f, err := os.Create(fmt.Sprintf("/tmp/%d.txt", atomic.AddInt64(&fileIndex, 1))) if err != nil { panic(err) } r := &someResource{f} libProfile.Add(r, 1) return r } func (r *someResource) Close() error { libProfile.Remove(r) return r.File.Close() } func trackAFunction() { tracked := new(byte) libProfile.Add(tracked, 1) defer libProfile.Remove(tracked) time.Sleep(time.Second) } func usesAResource() { res := MustResource() defer res.Close() for i := 0; i < 10; i++ { time.Sleep(time.Second) } } func main() { http.HandleFunc("/nonblock", func(rw http.ResponseWriter, req *http.Request) { go usesAResource() }) http.HandleFunc("/functiontrack", func(rw http.ResponseWriter, req *http.Request) { trackAFunction() }) http.HandleFunc("/block", func(rw http.ResponseWriter, req *http.Request) { usesAResource() }) log.Println("Running!") log.Println(http.ListenAndServe("localhost:6060", nil)) }
my_experiment_thing profile: total 6 4 @ 0x2245 0x5d961 # 0x2244 main.usesAResource+0x64 /Users/.../pproftest.go:64 2 @ 0x2245 0x2574 0x9c184 0x9d56f 0x9df7d 0x9aa07 0x5d961 # 0x2244 main.usesAResource+0x64 /Users/.../pproftest.go:64 # 0x2573 main.main.func3+0x13 /Users/.../pproftest.go:79 # 0x9c183 net/http.HandlerFunc.ServeHTTP+0x43 /usr/local/Cellar/go/1.7.1/libexec/src/net/http/server.go:1726 # 0x9d56e net/http.(*ServeMux).ServeHTTP+0x7e /usr/local/Cellar/go/1.7.1/libexec/src/net/http/server.go:2022 # 0x9df7c net/http.serverHandler.ServeHTTP+0x7c /usr/local/Cellar/go/1.7.1/libexec/src/net/http/server.go:2202 # 0x9aa06 net/http.(*conn).serve+0x4b6 /usr/local/Cellar/go/1.7.1/libexec/src/net/http/server.go:1579
brew install Graphviz
go tool pprof -png /tmp/mybinary 'localhost:6060/debug/pprof/my_experiment_thing?debug=1' > /tmp/exp.png
> go tool pprof 'localhost:6060/debug/pprof/my_experiment_thing?debug=1' Fetching profile from http://localhost:6060/debug/pprof/my_experiment_thing?debug=1 Saved profile in /Users/.../pprof/pprof.localhost:6060.my_experiment_thing.007.pb.gz Entering interactive mode (type "help" for commands) (pprof) top30 6 of 6 total ( 100%) flat flat% sum% cum cum% 6 100% 100% 6 100% main.usesAResource 0 0% 100% 2 33.33% main.main.func3 0 0% 100% 2 33.33% net/http.(*ServeMux).ServeHTTP 0 0% 100% 2 33.33% net/http.(*conn).serve 0 0% 100% 2 33.33% net/http.HandlerFunc.ServeHTTP 0 0% 100% 2 33.33% net/http.serverHandler.ServeHTTP 0 0% 100% 6 100% runtime.goexit (pprof)
Source: https://habr.com/ru/post/318336/
All Articles