From 33511fb959f8f0edd5e831a4b41523daf9d84e87 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Wed, 23 Sep 2020 14:06:28 +0300 Subject: [PATCH] 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(-) 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/