From 5c1567cdc064b68210aeeddc6bf76bf0a146a626 Mon Sep 17 00:00:00 2001 From: Ayan George Date: Tue, 6 Oct 2020 18:40:40 +0000 Subject: net/http/pprof: use Request.Context, not the deprecated CloseNotifier Prior to this commit, the profiling code had a sleep() function that waits and unblocks on either time.After() or a channel provided by an http.CloseNotifier derived from a supplied http.ResponseWriter. According to the documentation, http.CloseNotifier is deprecated: Deprecated: the CloseNotifier interface predates Go's context package. New code should use Request.Context instead. This patch does just that -- sleep() now takes an *http.Request and uses http.Request.Context() to signal when a request has been cancelled. Change-Id: I98702314addf494f5743a4f99172dc607389dbb8 GitHub-Last-Rev: c1e37a03ca28417ed5833618d3eeddb2eecccd09 GitHub-Pull-Request: golang/go#41756 Reviewed-on: https://go-review.googlesource.com/c/go/+/259157 Reviewed-by: Bryan C. Mills Reviewed-by: Hyang-Ah Hana Kim Reviewed-by: Emmanuel Odeke Trust: Bryan C. Mills Trust: Emmanuel Odeke Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/net/http/pprof/pprof.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/net/http/pprof') diff --git a/src/net/http/pprof/pprof.go b/src/net/http/pprof/pprof.go index 81df0448e9..5ff7fdc3de 100644 --- a/src/net/http/pprof/pprof.go +++ b/src/net/http/pprof/pprof.go @@ -93,14 +93,10 @@ func Cmdline(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, strings.Join(os.Args, "\x00")) } -func sleep(w http.ResponseWriter, d time.Duration) { - var clientGone <-chan bool - if cn, ok := w.(http.CloseNotifier); ok { - clientGone = cn.CloseNotify() - } +func sleep(r *http.Request, d time.Duration) { select { case <-time.After(d): - case <-clientGone: + case <-r.Context().Done(): } } @@ -142,7 +138,7 @@ func Profile(w http.ResponseWriter, r *http.Request) { fmt.Sprintf("Could not enable CPU profiling: %s", err)) return } - sleep(w, time.Duration(sec)*time.Second) + sleep(r, time.Duration(sec)*time.Second) pprof.StopCPUProfile() } @@ -171,7 +167,7 @@ func Trace(w http.ResponseWriter, r *http.Request) { fmt.Sprintf("Could not enable tracing: %s", err)) return } - sleep(w, time.Duration(sec*float64(time.Second))) + sleep(r, time.Duration(sec*float64(time.Second))) trace.Stop() } -- cgit v1.3 From 33511fb959f8f0edd5e831a4b41523daf9d84e87 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Wed, 23 Sep 2020 14:06:28 +0300 Subject: net/http/pprof: remove html/template dependency html/template indirectly uses reflect MethodByName, this causes linker to use conservative mode resulting in larger binaries. The template here is trivial and can be replaced by string manipulation. This reduces a binary using only net/http/pprof by ~2.5MB. Fixes #41569 Change-Id: I240e1daa6376182ff4961997ee3ec7b96cb07be8 Reviewed-on: https://go-review.googlesource.com/c/go/+/256900 Reviewed-by: Brad Fitzpatrick Reviewed-by: Hajime Hoshi Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Trust: Hajime Hoshi Trust: Brad Fitzpatrick --- src/go/build/deps_test.go | 2 +- src/net/http/pprof/pprof.go | 60 ++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 26 deletions(-) (limited to 'src/net/http/pprof') diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index fa8ecf10f4..42382d583c 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -449,7 +449,7 @@ var depsRules = ` OS, compress/gzip, regexp < internal/profile; - html/template, internal/profile, net/http, runtime/pprof, runtime/trace + html, internal/profile, net/http, runtime/pprof, runtime/trace < net/http/pprof; # RPC diff --git a/src/net/http/pprof/pprof.go b/src/net/http/pprof/pprof.go index 5ff7fdc3de..2bfcfb9545 100644 --- a/src/net/http/pprof/pprof.go +++ b/src/net/http/pprof/pprof.go @@ -61,11 +61,12 @@ import ( "bytes" "context" "fmt" - "html/template" + "html" "internal/profile" "io" "log" "net/http" + "net/url" "os" "runtime" "runtime/pprof" @@ -352,6 +353,13 @@ var profileDescriptions = map[string]string{ "trace": "A trace of execution of the current program. You can specify the duration in the seconds GET parameter. After you get the trace file, use the go tool trace command to investigate the trace.", } +type profileEntry struct { + Name string + Href string + Desc string + Count int +} + // Index responds with the pprof-formatted profile named by the request. // For example, "/debug/pprof/heap" serves the "heap" profile. // Index responds to a request for "/debug/pprof/" with an HTML page @@ -368,17 +376,11 @@ func Index(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "text/html; charset=utf-8") - type profile struct { - Name string - Href string - Desc string - Count int - } - var profiles []profile + var profiles []profileEntry for _, p := range pprof.Profiles() { - profiles = append(profiles, profile{ + profiles = append(profiles, profileEntry{ Name: p.Name(), - Href: p.Name() + "?debug=1", + Href: p.Name(), Desc: profileDescriptions[p.Name()], Count: p.Count(), }) @@ -386,7 +388,7 @@ func Index(w http.ResponseWriter, r *http.Request) { // Adding other profiles exposed from within this package for _, p := range []string{"cmdline", "profile", "trace"} { - profiles = append(profiles, profile{ + profiles = append(profiles, profileEntry{ Name: p, Href: p, Desc: profileDescriptions[p], @@ -397,12 +399,14 @@ func Index(w http.ResponseWriter, r *http.Request) { return profiles[i].Name < profiles[j].Name }) - if err := indexTmpl.Execute(w, profiles); err != nil { + if err := indexTmplExecute(w, profiles); err != nil { log.Print(err) } } -var indexTmpl = template.Must(template.New("index").Parse(` +func indexTmplExecute(w io.Writer, profiles []profileEntry) error { + var b bytes.Buffer + b.WriteString(` /debug/pprof/