Profilierung von Go-Code: Engpässe in der Praxis finden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum die Profilierung von Go-Code ein Muss ist

Die Entwicklung mit Go (Golang) ist bekannt für ihre Leistung und Effizienz. Selbst der schnellste Code kann jedoch langsamer werden, wenn die Besonderheiten der Arbeit mit Speicher, Goroutinen oder Ein-/Ausgabe nicht berücksichtigt werden. Profilierung ist der Prozess der Datenerfassung über die Programmausführung, der es ermöglicht, „unter die Haube“ zu schauen und zu verstehen, welche Funktionen die meiste CPU, den meisten Speicher oder die meiste Zeit verbrauchen.

In diesem Artikel werden wir die praktischen Profilierungswerkzeuge in Go untersuchen: pprof, trace und integrierte Benchmarks. Sie erfahren, wie Sie Engpässe finden und Code anhand realer Beispiele optimieren.



1. Grundlegende Profilierungswerkzeuge in Golang

Go bietet von Haus aus ein leistungsstarkes Arsenal für die Profilierung. Betrachten wir drei Schlüsselansätze:

  • pprof — Profilierung von CPU, Speicher, Sperren und Goroutinen.
  • trace — Ereignisverfolgung: Erstellung von Goroutinen, Systemaufrufe, GC.
  • benchmark — Integrierte Leistungstests mit go test -bench.

Um mit pprof zu beginnen, reicht es aus, net/http/pprof in Ihren HTTP-Server zu importieren oder runtime/pprof für CLI-Anwendungen zu verwenden.



1.1. So starten Sie die CPU-Profilierung

Der einfachste Weg ist, einen Endpunkt in Ihren HTTP-Server einzufügen:

package main

import ( "log" "net/http" _ "net/http/pprof")

func main() { go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() // Ihr Hauptcode select {}}

Öffnen Sie nach dem Start http://localhost:6060/debug/pprof/ – Sie sehen ein Dashboard. Um ein CPU-Profil für 30 Sekunden zu erstellen, führen Sie aus:

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

Dies lädt die Daten herunter und öffnet die interaktive pprof-Konsole.



2. Engpässe mit pprof finden: CPU und Speicher

Angenommen, wir haben eine Funktion, die ein großes Datenarray verarbeitet. Wir vermuten, dass sie langsam ist. Lassen Sie uns ein Testbeispiel schreiben und es profilieren.



2.1. Beispiel für langsamen Code

package main

import ( "fmt" "time")

func slowFunction(data []int) int { sum := 0 for _, v := range data { time.Sleep(1 * time.Microsecond) // simuliert Arbeit sum += v * v } return sum}

func main() { data := make([]int, 100000) for i := range data { data[i] = i } result := slowFunction(data) fmt.Println(result)}

Starten wir die CPU-Profilierung:

go run main.go &go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=10

Im Browser öffnet sich eine Visualisierung – ein Aufrufgraph (call graph). Die Dicke der Kanten zeigt, wie viel Zeit jede Funktion in Anspruch genommen hat. Wir sehen sofort, dass slowFunction und time.Sleep die Hauptverbraucher der CPU sind.



2.2. Speicheranalyse (Heap-Profil)

Um Speicherlecks oder Objekte zu finden, die zu viel Platz belegen, verwenden Sie:

go tool pprof http://localhost:6060/debug/pprof/heap

In der interaktiven Konsole können Sie den Befehl top ausführen:

(pprof) top10Showing nodes accounting for 80MB, 100% of 80MB total      flat  flat%   sum%        cum   cum%      40MB 50.00% 50.00%       40MB 50.00%  main.slowFunction      20MB 25.00% 75.00%       20MB 25.00%  main.createLargeSlice      20MB 25.00% 100.00%      20MB 25.00%  runtime.makeslice

Dies zeigt, welche Funktionen den meisten Speicher allozieren. Wenn Sie sehen, dass main.slowFunction 40MB belegt, sollten Sie über ein Refactoring nachdenken – zum Beispiel die Wiederverwendung von Slice

Blogs

Buchempfehlungen