Sobes.tech
Middle

Wie kann man den Speicherverbrauch in Go messen und was ist pprof?

sobes.tech KI

Antwort von AI

Die Speichernutzung in Go kann auf verschiedene Weisen gemessen werden:

  • runtime.MemStats: Bietet einen Schnappschuss der Speicherstatistiken, einschließlich Heap-Größe, Anzahl der Objekte, Garbage Collection usw. Nützlich, um eine allgemeine Übersicht über die Speicherverteilung zu erhalten.

  • pprof-Profiling: Ein leistungsstarkes Werkzeug zur Analyse der Leistung und Ressourcennutzung, einschließlich Speicher. Ermöglicht das Sammeln von Heap-Profilen zu verschiedenen Zeitpunkten und deren Analyse, um Engpässe und Speicherlecks zu identifizieren.

  • debug.FreeOSMemory(): Gibt Speicher zwangsweise an das Betriebssystem frei. Kann indirekt helfen zu verstehen, wie viel Speicher vom Go-Laufzeitumgebung gehalten wird.

pprof (net/http/pprof) ist ein Paket in der Standardbibliothek von Go, das sich mit dem pprof-Profiler aus dem Paket runtime/pprof integriert. Es bietet HTTP-Schnittstellen zum Sammeln von Profilen verschiedener Ressourcen, einschließlich CPU, Heap (Speicher), Sperren, Goroutinen und Mutexen.

Um es zu verwenden:

  1. Importiere net/http/pprof.
  2. Starte einen HTTP-Server.
  3. Greife auf die entsprechenden URLs (/debug/pprof/) zu, um Profile zu erhalten.
  4. Nutze das Tool go tool pprof, um die gesammelten Daten zu analysieren.

Beispiel für die Verwendung von runtime.MemStats:

import (
	"fmt"
	"runtime"
	"time"
)

func main() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m) // Lese Speicherstatistiken
	fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
	fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
	fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
	fmt.Printf("\tNumGC = %v\n", m.NumGC)

	// Beispiel für Speicherverbrauch
	_ = make([]byte, 1024*1024*10) // Reserviere 10MB

	time.Sleep(100 * time.Millisecond) // Warte, damit GC laufen kann

	runtime.ReadMemStats(&m)
	fmt.Printf("Nach Allokation: Alloc = %v MiB", bToMb(m.Alloc))
	fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
	fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
	fmt.Printf("\tNumGC = %v\n", m.NumGC)
}

func bToMb(b uint64) uint64 {
	return b / 1024 / 1024
}

Beispiel für die Verwendung von pprof in einem HTTP-Server:

import (
	_ "net/http/pprof" // Importieren, um pprof-Handler zu registrieren
	"net/http"
	"log"
)

func main() {
	log.Println(http.ListenAndServe(":6060", nil)) // Auf Port 6060 hören
}

Nach dem Start dieses Codes kann man auf http://localhost:6060/debug/pprof/ zugreifen, um verschiedene Profile zu erhalten. Für die Heap-Analyse kann go tool pprof http://localhost:6060/debug/pprof/heap verwendet werden.