OSDN Git Service

Update to current version of Go library.
[pf3gnuchains/gcc-fork.git] / libgo / go / http / pprof / pprof.go
1 // Copyright 2010 The Go Authors.  All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package pprof serves via its HTTP server runtime profiling data
6 // in the format expected by the pprof visualization tool.
7 // For more information about pprof, see
8 // http://code.google.com/p/google-perftools/.
9 //
10 // The package is typically only imported for the side effect of
11 // registering its HTTP handlers.
12 // The handled paths all begin with /debug/pprof/.
13 //
14 // To use pprof, link this package into your program:
15 //      import _ "http/pprof"
16 //
17 // Then use the pprof tool to look at the heap profile:
18 //
19 //      pprof http://localhost:6060/debug/pprof/heap
20 //
21 // Or to look at a 30-second CPU profile:
22 //
23 //      pprof http://localhost:6060/debug/pprof/profile
24 //
25 package pprof
26
27 import (
28         "bufio"
29         "bytes"
30         "fmt"
31         "http"
32         "os"
33         "runtime"
34         "runtime/pprof"
35         "strconv"
36         "strings"
37         "time"
38 )
39
40 func init() {
41         http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
42         http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
43         http.Handle("/debug/pprof/heap", http.HandlerFunc(Heap))
44         http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
45 }
46
47 // Cmdline responds with the running program's
48 // command line, with arguments separated by NUL bytes.
49 // The package initialization registers it as /debug/pprof/cmdline.
50 func Cmdline(w http.ResponseWriter, r *http.Request) {
51         w.Header().Set("Content-Type", "text/plain; charset=utf-8")
52         fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
53 }
54
55 // Heap responds with the pprof-formatted heap profile.
56 // The package initialization registers it as /debug/pprof/heap.
57 func Heap(w http.ResponseWriter, r *http.Request) {
58         w.Header().Set("Content-Type", "text/plain; charset=utf-8")
59         pprof.WriteHeapProfile(w)
60 }
61
62 // Profile responds with the pprof-formatted cpu profile.
63 // The package initialization registers it as /debug/pprof/profile.
64 func Profile(w http.ResponseWriter, r *http.Request) {
65         sec, _ := strconv.Atoi64(r.FormValue("seconds"))
66         if sec == 0 {
67                 sec = 30
68         }
69
70         // Set Content Type assuming StartCPUProfile will work,
71         // because if it does it starts writing.
72         w.Header().Set("Content-Type", "application/octet-stream")
73         if err := pprof.StartCPUProfile(w); err != nil {
74                 // StartCPUProfile failed, so no writes yet.
75                 // Can change header back to text content
76                 // and send error code.
77                 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
78                 w.WriteHeader(http.StatusInternalServerError)
79                 fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
80                 return
81         }
82         time.Sleep(sec * 1e9)
83         pprof.StopCPUProfile()
84 }
85
86 // Symbol looks up the program counters listed in the request,
87 // responding with a table mapping program counters to function names.
88 // The package initialization registers it as /debug/pprof/symbol.
89 func Symbol(w http.ResponseWriter, r *http.Request) {
90         w.Header().Set("Content-Type", "text/plain; charset=utf-8")
91
92         // We have to read the whole POST body before
93         // writing any output.  Buffer the output here.
94         var buf bytes.Buffer
95
96         // We don't know how many symbols we have, but we
97         // do have symbol information.  Pprof only cares whether
98         // this number is 0 (no symbols available) or > 0.
99         fmt.Fprintf(&buf, "num_symbols: 1\n")
100
101         var b *bufio.Reader
102         if r.Method == "POST" {
103                 b = bufio.NewReader(r.Body)
104         } else {
105                 b = bufio.NewReader(strings.NewReader(r.URL.RawQuery))
106         }
107
108         for {
109                 word, err := b.ReadSlice('+')
110                 if err == nil {
111                         word = word[0 : len(word)-1] // trim +
112                 }
113                 pc, _ := strconv.Btoui64(string(word), 0)
114                 if pc != 0 {
115                         f := runtime.FuncForPC(uintptr(pc))
116                         if f != nil {
117                                 fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name())
118                         }
119                 }
120
121                 // Wait until here to check for err; the last
122                 // symbol will have an err because it doesn't end in +.
123                 if err != nil {
124                         if err != os.EOF {
125                                 fmt.Fprintf(&buf, "reading request: %v\n", err)
126                         }
127                         break
128                 }
129         }
130
131         w.Write(buf.Bytes())
132 }