From e857dd5d3f1e77bcbed0884324588d1b63075555 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 25 Mar 2011 12:50:12 -0400 Subject: [PATCH] http/pprof: cpu profiling support R=r CC=golang-dev https://golang.org/cl/4280060 --- src/pkg/http/pprof/pprof.go | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/pkg/http/pprof/pprof.go b/src/pkg/http/pprof/pprof.go index 0bac26687d..bc79e21832 100644 --- a/src/pkg/http/pprof/pprof.go +++ b/src/pkg/http/pprof/pprof.go @@ -18,6 +18,10 @@ // // pprof http://localhost:6060/debug/pprof/heap // +// Or to look at a 30-second CPU profile: +// +// pprof http://localhost:6060/debug/pprof/profile +// package pprof import ( @@ -29,10 +33,12 @@ import ( "runtime/pprof" "strconv" "strings" + "time" ) func init() { http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline)) + http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile)) http.Handle("/debug/pprof/heap", http.HandlerFunc(Heap)) http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol)) } @@ -41,22 +47,46 @@ func init() { // command line, with arguments separated by NUL bytes. // The package initialization registers it as /debug/pprof/cmdline. func Cmdline(w http.ResponseWriter, r *http.Request) { - w.Header().Set("content-type", "text/plain; charset=utf-8") + w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, strings.Join(os.Args, "\x00")) } // Heap responds with the pprof-formatted heap profile. // The package initialization registers it as /debug/pprof/heap. func Heap(w http.ResponseWriter, r *http.Request) { - w.Header().Set("content-type", "text/plain; charset=utf-8") + w.Header().Set("Content-Type", "text/plain; charset=utf-8") pprof.WriteHeapProfile(w) } +// Profile responds with the pprof-formatted cpu profile. +// The package initialization registers it as /debug/pprof/profile. +func Profile(w http.ResponseWriter, r *http.Request) { + sec, _ := strconv.Atoi64(r.FormValue("seconds")) + if sec == 0 { + sec = 30 + } + + // Set Content Type assuming StartCPUProfile will work, + // because if it does it starts writing. + w.Header().Set("Content-Type", "application/octet-stream") + if err := pprof.StartCPUProfile(w); err != nil { + // StartCPUProfile failed, so no writes yet. + // Can change header back to text content + // and send error code. + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err) + return + } + time.Sleep(sec * 1e9) + pprof.StopCPUProfile() +} + // Symbol looks up the program counters listed in the request, // responding with a table mapping program counters to function names. // The package initialization registers it as /debug/pprof/symbol. func Symbol(w http.ResponseWriter, r *http.Request) { - w.Header().Set("content-type", "text/plain; charset=utf-8") + w.Header().Set("Content-Type", "text/plain; charset=utf-8") // We don't know how many symbols we have, but we // do have symbol information. Pprof only cares whether -- 2.50.0