package main // run this and then hit: // http://localhost:6060/debug/pprof/ // // Also run from the command line: // go tool pprof 'localhost:6060/debug/pprof/wit_pprof_experiment_thing?debug=1' // // https://medium.com/@cep21/creating-custom-go-profiles-with-pprof-b737dfc58e11 import "fmt" import "log" import "net/http" import _ "net/http/pprof" // the _ means only the init() is needed import "os" import "runtime/pprof" import "sync/atomic" import "time" var libProfile *pprof.Profile func init() { profName := "wit_pprof_experiment_thing" // this ends up in the URL 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)) }