internal/lsp: add memory debugging page
Display the memory statistics provided by the runtime package.
Change-Id: I3ae9c51a847fc1808c15faaadbbdc7a4874c11f0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/179517
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/debug/serve.go b/internal/lsp/debug/serve.go
index 3ea564e..43460ec 100644
--- a/internal/lsp/debug/serve.go
+++ b/internal/lsp/debug/serve.go
@@ -14,6 +14,8 @@
"net/http"
_ "net/http/pprof" // pull in the standard pprof handlers
"path"
+ "runtime"
+ "strconv"
"sync"
"golang.org/x/tools/internal/span"
@@ -63,6 +65,7 @@
http.HandleFunc("/view/", Render(viewTmpl, getView))
http.HandleFunc("/file/", Render(fileTmpl, getFile))
http.HandleFunc("/info", Render(infoTmpl, getInfo))
+ http.HandleFunc("/memory", Render(memoryTmpl, getMemory))
}
// AddCache adds a cache to the set being served
@@ -171,6 +174,12 @@
return template.HTML(buf.String())
}
+func getMemory(r *http.Request) interface{} {
+ var m runtime.MemStats
+ runtime.ReadMemStats(&m)
+ return m
+}
+
// AddSession adds a session to the set being served
func AddSession(session Session) {
mu.Lock()
@@ -235,6 +244,22 @@
}
}
+func commas(s string) string {
+ for i := len(s); i > 3; {
+ i -= 3
+ s = s[:i] + "," + s[i:]
+ }
+ return s
+}
+
+func fuint64(v uint64) string {
+ return commas(strconv.FormatUint(v, 10))
+}
+
+func fuint32(v uint32) string {
+ return commas(strconv.FormatUint(uint64(v), 10))
+}
+
var BaseTemplate = template.Must(template.New("").Parse(`
<html>
<head>
@@ -244,11 +269,16 @@
display:inline-block;
width:6rem;
}
+td.value {
+ text-align: right;
+}
</style>
+{{block "head" .}}{{end}}
</head>
<body>
<a href="/">Main</a>
<a href="/info">Info</a>
+<a href="/memory">Memory</a>
<a href="/debug/">Debug</a>
<hr>
<h1>{{template "title" .}}</h1>
@@ -262,7 +292,10 @@
{{define "sessionlink"}}<a href="/session/{{.}}">Session {{.}}</a>{{end}}
{{define "viewlink"}}<a href="/view/{{.}}">View {{.}}</a>{{end}}
{{define "filelink"}}<a href="/file/{{.Session.ID}}/{{.Hash}}">{{.URI}}</a>{{end}}
-`))
+`)).Funcs(template.FuncMap{
+ "fuint64": fuint64,
+ "fuint32": fuint32,
+})
var mainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
{{define "title"}}GoPls server information{{end}}
@@ -283,6 +316,36 @@
{{end}}
`))
+var memoryTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
+{{define "title"}}GoPls memory usage{{end}}
+{{define "head"}}<meta http-equiv="refresh" content="5">{{end}}
+{{define "body"}}
+<h2>Stats</h2>
+<table>
+<tr><td class="label">Allocated bytes</td><td class="value">{{fuint64 .HeapAlloc}}</td></tr>
+<tr><td class="label">Total allocated bytes</td><td class="value">{{fuint64 .TotalAlloc}}</td></tr>
+<tr><td class="label">System bytes</td><td class="value">{{fuint64 .Sys}}</td></tr>
+<tr><td class="label">Heap system bytes</td><td class="value">{{fuint64 .HeapSys}}</td></tr>
+<tr><td class="label">Malloc calls</td><td class="value">{{fuint64 .Mallocs}}</td></tr>
+<tr><td class="label">Frees</td><td class="value">{{fuint64 .Frees}}</td></tr>
+<tr><td class="label">Idle heap bytes</td><td class="value">{{fuint64 .HeapIdle}}</td></tr>
+<tr><td class="label">In use bytes</td><td class="value">{{fuint64 .HeapInuse}}</td></tr>
+<tr><td class="label">Released to system bytes</td><td class="value">{{fuint64 .HeapReleased}}</td></tr>
+<tr><td class="label">Heap object count</td><td class="value">{{fuint64 .HeapObjects}}</td></tr>
+<tr><td class="label">Stack in use bytes</td><td class="value">{{fuint64 .StackInuse}}</td></tr>
+<tr><td class="label">Stack from system bytes</td><td class="value">{{fuint64 .StackSys}}</td></tr>
+<tr><td class="label">Bucket hash bytes</td><td class="value">{{fuint64 .BuckHashSys}}</td></tr>
+<tr><td class="label">GC metaata bytes</td><td class="value">{{fuint64 .GCSys}}</td></tr>
+<tr><td class="label">Off heap bytes</td><td class="value">{{fuint64 .OtherSys}}</td></tr>
+</table>
+<h2>By size</h2>
+<table>
+<tr><th>Size</th><th>Mallocs</th><th>Frees</th></tr>
+{{range .BySize}}<tr><td class="value">{{fuint32 .Size}}</td><td class="value">{{fuint64 .Mallocs}}</td><td class="value">{{fuint64 .Frees}}</td></tr>{{end}}
+</table>
+{{end}}
+`))
+
var debugTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
{{define "title"}}GoPls Debug pages{{end}}
{{define "body"}}