]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgo/go/net/http/pprof/pprof.go
libgo: Update to current sources.
[thirdparty/gcc.git] / libgo / go / net / http / pprof / pprof.go
CommitLineData
7a938933
ILT
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:
cbb6491d 15// import _ "net/http/pprof"
7a938933 16//
bd2e46c8
ILT
17// If your application is not already running an http server, you
18// need to start one. Add "net/http" and "log" to your imports and
19// the following code to your main function:
20//
21// go func() {
22// log.Println(http.ListenAndServe("localhost:6060", nil))
23// }()
24//
7a938933
ILT
25// Then use the pprof tool to look at the heap profile:
26//
cbb6491d 27// go tool pprof http://localhost:6060/debug/pprof/heap
7a938933 28//
f72f4169
ILT
29// Or to look at a 30-second CPU profile:
30//
cbb6491d
ILT
31// go tool pprof http://localhost:6060/debug/pprof/profile
32//
4ccad563
ILT
33// Or to look at the goroutine blocking profile:
34//
35// go tool pprof http://localhost:6060/debug/pprof/block
36//
501699af 37// Or to view all available profiles:
cbb6491d 38//
501699af 39// go tool pprof http://localhost:6060/debug/pprof/
cbb6491d
ILT
40//
41// For a study of the facility in action, visit
42//
43// http://blog.golang.org/2011/06/profiling-go-programs.html
f72f4169 44//
7a938933
ILT
45package pprof
46
47import (
48 "bufio"
9ff56c95 49 "bytes"
7a938933 50 "fmt"
501699af 51 "html/template"
2fd401c8 52 "io"
501699af 53 "log"
9c63abc9 54 "net/http"
7a938933
ILT
55 "os"
56 "runtime"
57 "runtime/pprof"
58 "strconv"
59 "strings"
f72f4169 60 "time"
7a938933
ILT
61)
62
63func init() {
501699af 64 http.Handle("/debug/pprof/", http.HandlerFunc(Index))
7a938933 65 http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
f72f4169 66 http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
7a938933
ILT
67 http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
68}
69
70// Cmdline responds with the running program's
71// command line, with arguments separated by NUL bytes.
72// The package initialization registers it as /debug/pprof/cmdline.
73func Cmdline(w http.ResponseWriter, r *http.Request) {
f72f4169 74 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
7a938933
ILT
75 fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
76}
77
f72f4169
ILT
78// Profile responds with the pprof-formatted cpu profile.
79// The package initialization registers it as /debug/pprof/profile.
80func Profile(w http.ResponseWriter, r *http.Request) {
d5363590 81 sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
f72f4169
ILT
82 if sec == 0 {
83 sec = 30
84 }
85
86 // Set Content Type assuming StartCPUProfile will work,
87 // because if it does it starts writing.
88 w.Header().Set("Content-Type", "application/octet-stream")
89 if err := pprof.StartCPUProfile(w); err != nil {
90 // StartCPUProfile failed, so no writes yet.
91 // Can change header back to text content
92 // and send error code.
93 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
94 w.WriteHeader(http.StatusInternalServerError)
95 fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
96 return
97 }
7b1c3dd9 98 time.Sleep(time.Duration(sec) * time.Second)
f72f4169
ILT
99 pprof.StopCPUProfile()
100}
101
7a938933
ILT
102// Symbol looks up the program counters listed in the request,
103// responding with a table mapping program counters to function names.
104// The package initialization registers it as /debug/pprof/symbol.
105func Symbol(w http.ResponseWriter, r *http.Request) {
f72f4169 106 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
7a938933 107
9ff56c95
ILT
108 // We have to read the whole POST body before
109 // writing any output. Buffer the output here.
110 var buf bytes.Buffer
111
7a938933
ILT
112 // We don't know how many symbols we have, but we
113 // do have symbol information. Pprof only cares whether
114 // this number is 0 (no symbols available) or > 0.
9ff56c95 115 fmt.Fprintf(&buf, "num_symbols: 1\n")
7a938933
ILT
116
117 var b *bufio.Reader
118 if r.Method == "POST" {
119 b = bufio.NewReader(r.Body)
120 } else {
121 b = bufio.NewReader(strings.NewReader(r.URL.RawQuery))
122 }
123
124 for {
125 word, err := b.ReadSlice('+')
126 if err == nil {
127 word = word[0 : len(word)-1] // trim +
128 }
d5363590 129 pc, _ := strconv.ParseUint(string(word), 0, 64)
7a938933
ILT
130 if pc != 0 {
131 f := runtime.FuncForPC(uintptr(pc))
132 if f != nil {
9ff56c95 133 fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name())
7a938933
ILT
134 }
135 }
136
137 // Wait until here to check for err; the last
138 // symbol will have an err because it doesn't end in +.
139 if err != nil {
2fd401c8 140 if err != io.EOF {
9ff56c95
ILT
141 fmt.Fprintf(&buf, "reading request: %v\n", err)
142 }
7a938933
ILT
143 break
144 }
145 }
9ff56c95
ILT
146
147 w.Write(buf.Bytes())
7a938933 148}
501699af
ILT
149
150// Handler returns an HTTP handler that serves the named profile.
151func Handler(name string) http.Handler {
152 return handler(name)
153}
154
155type handler string
156
157func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
158 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
159 debug, _ := strconv.Atoi(r.FormValue("debug"))
160 p := pprof.Lookup(string(name))
161 if p == nil {
162 w.WriteHeader(404)
163 fmt.Fprintf(w, "Unknown profile: %s\n", name)
164 return
165 }
166 p.WriteTo(w, debug)
167 return
168}
169
170// Index responds with the pprof-formatted profile named by the request.
171// For example, "/debug/pprof/heap" serves the "heap" profile.
172// Index responds to a request for "/debug/pprof/" with an HTML page
173// listing the available profiles.
174func Index(w http.ResponseWriter, r *http.Request) {
175 if strings.HasPrefix(r.URL.Path, "/debug/pprof/") {
176 name := r.URL.Path[len("/debug/pprof/"):]
177 if name != "" {
178 handler(name).ServeHTTP(w, r)
179 return
180 }
181 }
182
183 profiles := pprof.Profiles()
184 if err := indexTmpl.Execute(w, profiles); err != nil {
185 log.Print(err)
186 }
187}
188
189var indexTmpl = template.Must(template.New("index").Parse(`<html>
190<head>
191<title>/debug/pprof/</title>
192</head>
193/debug/pprof/<br>
194<br>
195<body>
196profiles:<br>
197<table>
198{{range .}}
199<tr><td align=right>{{.Count}}<td><a href="/debug/pprof/{{.Name}}?debug=1">{{.Name}}</a>
200{{end}}
201</table>
202<br>
203<a href="/debug/pprof/goroutine?debug=2">full goroutine stack dump</a><br>
204</body>
205</html>
206`))