]> Cypherpunks repositories - gostls13.git/commitdiff
http/pprof: cpu profiling support
authorRuss Cox <rsc@golang.org>
Fri, 25 Mar 2011 16:50:12 +0000 (12:50 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 25 Mar 2011 16:50:12 +0000 (12:50 -0400)
R=r
CC=golang-dev
https://golang.org/cl/4280060

src/pkg/http/pprof/pprof.go

index 0bac26687d73d842b99793d5b75c142d8ee4a053..bc79e218320cb9b0c4941866cc9fa01b85fe8ecb 100644 (file)
 //
 //     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