Leistungsanalyse
Wenn ein Programm fertiggestellt ist, erwarten wir nicht nur, dass es läuft, sondern auch, dass es eine stabile und effiziente Anwendung ist. Durch verschiedene Tests können wir die Stabilität des Programms weitgehend gewährleisten. Ob ein Programm effizient ist, erfordert jedoch eine Leistungsanalyse. In den vorherigen Inhalten war Benchmark die einzige Methode zur Leistungsanalyse, um die durchschnittliche Ausführungszeit und Speicherzuweisung einer Funktionseinheit zu testen. In der Praxis gibt es jedoch viele weitere Anforderungen an die Leistungsanalyse, wie die Analyse der gesamten CPU-Auslastung, Speichernutzung, Heap-Zuweisung, Goroutine-Status und Hot-Code-Pfade. Dies kann Benchmark nicht leisten. Glücklicherweise integriert die Go-Toolchain viele Leistungsanalyse-Tools für Entwickler.
Escape-Analyse
In Go wird die Speicherzuweisung von Variablen vom Compiler bestimmt, normalerweise auf dem Stack oder dem Heap. Wenn eine Variable, die eigentlich auf dem Stack zugewiesen werden sollte, auf dem Heap zugewiesen wird, nennt man dies Escape. Die Escape-Analyse analysiert die Speicherzuweisung im Programm. Da sie zur Kompilierzeit erfolgt, ist sie eine statische Analyse.
TIP
Siehe Speicherzuweisung für Details zur Go-Speicherzuweisung.
Referenz auf lokalen Zeiger
package main
func main() {
GetPerson()
}
type Person struct {
Name string
Mom *Person
}
func GetPerson() Person {
mom := Person{Name: "lili"}
son := Person{Name: "jack", Mom: &mom}
return son
}Die Variable mom in der Funktion GetPerson sollte eigentlich auf dem Stack zugewiesen werden, da sie innerhalb der Funktion erstellt wurde. Da sie jedoch vom Feld Mom von son referenziert wird und son als Rückgabewert zurückgegeben wird, weist der Compiler sie auf dem Heap zu.
Verwenden Sie den folgenden Befehl für die Escape-Analyse:
$ go build -gcflags="-m -m -l"Closure-Referenz
Wenn eine Closure auf Variablen außerhalb der Funktion verweist, entweicht diese Variable ebenfalls auf den Heap.
Unzureichender Platz
Wenn der Stack-Speicher nicht ausreicht, entweichen Variablen ebenfalls auf den Heap.
Unbekannte Länge
Wenn die Länge eines Slices eine Variable ist, entweicht sie aufgrund der unbekannten Länge (Maps tun dies nicht).
pprof
pprof (program profiling) ist ein leistungsstarkes Tool zur Programmanalyse. Es nimmt Stichproben von Laufzeitdaten und deckt CPU, Speicher, Goroutinen, Locks, Stack-Informationen und viele weitere Aspekte ab.
Die Verwendung von pprof besteht aus zwei Schritten:
- Daten sammeln
- Ergebnisse analysieren
Sammlung
Es gibt zwei Methoden zur Datensammlung: automatisch und manuell.
Manuell
Manuelle Sammlung bedeutet die Kontrolle über Code. Der Vorteil ist die Kontrolle, Flexibilität und Anpassbarkeit. Zur direkten Verwendung von pprof im Code muss das Paket runtime/pprof importiert werden.
package main
import (
"log"
"os"
"runtime/pprof"
)
func main() {
Do()
w, _ := os.Create("heap.pb")
heapProfile := pprof.Lookup("heap")
err := heapProfile.WriteTo(w, 0)
if err != nil {
log.Fatal(err)
}
}pprof.Lookup unterstützt folgende Parameter:
profiles.m = map[string]*Profile{
"goroutine": goroutineProfile,
"threadcreate": threadcreateProfile,
"heap": heapProfile,
"allocs": allocsProfile,
"block": blockProfile,
"mutex": mutexProfile,
}Automatisch
Das Paket net/http/pprof verpackt die Analysefunktionen als HTTP-Schnittstellen und registriert sie im Standard-Router.
package main
import (
"net/http"
// Importieren Sie dieses Paket
_ "net/http/pprof"
)
func main() {
go func(){
http.ListenAndServe(":8080", nil)
}
for {
Do()
}
}Besuchen Sie http://127.0.0.1:8080/debug/pprof im Browser, um die Analyse-Seite zu öffnen.
Analyse
Nachdem Sie die Datendateien gesammelt haben, gibt es zwei Möglichkeiten zur Analyse: Kommandozeile oder Web. Beide erfordern das pprof-Kommandozeilen-Tool, das standardmäßig in Go integriert ist.
Kommandozeile
$ go tool pprof heap.pbBei Web-Sammlung ersetzen Sie den Dateinamen durch die Web-URL:
$ go tool pprof -http :8080 http://127.0.0.1/debug/pprof/heapVerwenden Sie den top-Befehl, um eine Übersicht zu erhalten:
(pprof) top 5
Showing nodes accounting for 117.49MB, 100% of 117.49MB total
flat flat% sum% cum cum%
117.49MB 100% 100% 117.49MB 100% main.makeSlice (inline)
0 0% 100% 117.49MB 100% main.Do
0 0% 100% 117.49MB 100% main.main
0 0% 100% 117.49MB 100% runtime.mainflat: Die von der aktuellen Funktion verbrauchten Ressourcencum: Die Summe der von der aktuellen Funktion und ihrer Aufrufkette verbrauchten Ressourcenflat%: flat/totalcum%: cum/total
Web
$ go tool pprof -http :8080 heap.pbDie Web-Seite bietet 6 Ansichten:
- Top
- Graph
- Flame Graph
- Peek
- Source
- Disassemble
Für die Speicheranalyse gibt es vier Dimensionen:
alloc_objects: Anzahl aller bisher zugewiesenen Objektealloc_space: Bisher zugewiesener Speicherplatzinuse_objects: Anzahl der aktuell verwendeten Objekteinuse_space: Aktuell verwendeter Speicherplatz
trace
pprof analysiert hauptsächlich den Ressourcenverbrauch des Programms, während trace besser für das Verfolgen der Programmlaufdetails geeignet ist.
$ go tool trace trace.outTrace enthält folgende Hauptbereiche:
- Event timelines for running goroutines
- Profiles
- User-defined tasks and regions
- Garbage collection metrics
