Skip to content

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

go
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:

bash
$ 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:

  1. Daten sammeln
  2. 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.

go
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:

go
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.

go
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

bash
$ go tool pprof heap.pb

Bei Web-Sammlung ersetzen Sie den Dateinamen durch die Web-URL:

bash
$ go tool pprof -http :8080 http://127.0.0.1/debug/pprof/heap

Verwenden 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.main
  • flat: Die von der aktuellen Funktion verbrauchten Ressourcen
  • cum: Die Summe der von der aktuellen Funktion und ihrer Aufrufkette verbrauchten Ressourcen
  • flat%: flat/total
  • cum%: cum/total

Web

bash
$ go tool pprof -http :8080 heap.pb

Die 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 Objekte
  • alloc_space: Bisher zugewiesener Speicherplatz
  • inuse_objects: Anzahl der aktuell verwendeten Objekte
  • inuse_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.

bash
$ go tool trace trace.out

Trace enthält folgende Hauptbereiche:

  • Event timelines for running goroutines
  • Profiles
  • User-defined tasks and regions
  • Garbage collection metrics

Golang by www.golangdev.cn edit