Heim >Backend-Entwicklung >Golang >Zeigeroperationen und CPU-/Speichernutzung verstehen
Der PHP-Editor Banana führt Sie in Zeigeroperationen und CPU-/Speichernutzung ein. In der Programmierung ist die Zeigermanipulation ein leistungsstarkes Werkzeug, das direkt auf Daten im Speicher zugreifen und diese ändern kann. Durch das Verständnis von Zeigeroperationen können Sie die Leistung Ihres Codes besser steuern und optimieren. Darüber hinaus ist es für die Optimierung von Programmen sehr wichtig, die CPU- und Speichernutzung zu verstehen. Durch die Überwachung und Analyse der CPU- und Speichernutzung können Sie potenzielle Leistungsprobleme erkennen und geeignete Maßnahmen ergreifen, um die Effizienz des Programmbetriebs zu verbessern. In diesem Artikel stellen wir Ihnen die relevanten Kenntnisse zu Zeigeroperationen und CPU-/Speichernutzung im Detail vor, damit Sie diese besser verstehen und anwenden können.
Ich habe mit einem Arbeitskollegen darüber diskutiert, ob es effizienter wäre, einen Zeiger auf eine Funktion zu übergeben und/oder einen Zeiger zurückzugeben.
Ich habe einige Benchmark-Funktionen zusammengestellt, um verschiedene Vorgehensweisen zu testen. Diese Funktionen nehmen grundsätzlich eine Variable, konvertieren sie und geben sie zurück. Wir haben 4 verschiedene Methoden:
package main import ( "fmt" "testing" ) type mystruct struct { mystring string } func acceptparamreturnvariable(s mystruct) mystruct { ns := mystruct{ fmt.sprintf("i'm quoting this: \"%s\"", s.mystring), } return ns } func acceptparamreturnpointer(s mystruct) *mystruct { ns := mystruct{ fmt.sprintf("i'm quoting this: \"%s\"", s.mystring), } return &ns } func acceptpointerparamreturnvariable(s *mystruct) mystruct { ns := mystruct{ fmt.sprintf("i'm quoting this: \"%s\"", s.mystring), } return ns } func acceptpointerparamnoreturn(s *mystruct) { s.mystring = fmt.sprintf("i'm quoting this: \"%s\"", s.mystring) } func benchmarknormalparamreturnvariable(b *testing.b) { s := mystruct{ mystring: "hello world", } var ns mystruct for i := 0; i < b.n; i++ { ns = acceptparamreturnvariable(s) } _ = ns } func benchmarknormalparamreturnpointer(b *testing.b) { s := mystruct{ mystring: "hello world", } var ns *mystruct for i := 0; i < b.n; i++ { ns = acceptparamreturnpointer(s) } _ = ns } func benchmarkpointerparamreturnvariable(b *testing.b) { s := mystruct{ mystring: "hello world", } var ns mystruct for i := 0; i < b.n; i++ { ns = acceptpointerparamreturnvariable(&s) } _ = ns } func benchmarkpointerparamnoreturn(b *testing.b) { s := mystruct{ mystring: "hello world", } for i := 0; i < b.n; i++ { acceptpointerparamnoreturn(&s) } _ = s }
Ich fand die Ergebnisse ziemlich überraschend.
$ go test -run=XXXX -bench=. -benchmem goos: darwin goarch: amd64 pkg: XXXX cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz BenchmarkNormalParamReturnVariable-16 10538138 103.3 ns/op 48 B/op 2 allocs/op BenchmarkNormalParamReturnPointer-16 9526380 201.2 ns/op 64 B/op 3 allocs/op BenchmarkPointerParamReturnVariable-16 7542066 147.0 ns/op 48 B/op 2 allocs/op BenchmarkPointerParamNoReturn-16 45897 119265 ns/op 924351 B/op 5 allocs/op
Bevor ich dies ausführte, dachte ich, dass der vierte Test der effizienteste Weg wäre, da im Rahmen der aufgerufenen Funktion keine neuen Variablen erstellt werden und nur die Speicheradresse übergeben wird. Allerdings scheint der vierte Test der geringste zu sein effizient, Nimmt die meiste Zeit in Anspruch und verbraucht den meisten Speicher.
Kann mir das jemand erklären oder mir ein paar gute Leselinks zur Verfügung stellen, die das erklären?
Der von Ihnen durchgeführte Benchmark beantwortet die von Ihnen gestellte Frage nicht. Es stellt sich heraus, dass Mikrobenchmarking äußerst schwierig ist – nicht nur in der mobilen Welt, sondern im Allgemeinen.
Zurück zum Thema Effizienz. Normalerweise erfolgt die Übergabe von Zeigern auf Funktionen nicht an den Heap. Normalerweise entkommen von Funktionen zurückgegebene Zeiger auf den Heap. Normalerweise ist hier das Schlüsselwort. Man kann nicht wirklich sagen, wann der Compiler etwas auf dem Stapel und wann er etwas auf dem Heap zuweist. Das ist kein kleines Problem. Eine sehr gute kurze Erklärung gibt es hier.
Aber wenn Sie es wissen müssen, können Sie fragen. Sie können damit beginnen, einfach die vom Compiler getroffenen Optimierungsentscheidungen auszudrucken. Sie können dies tun, indem Sie m
标志传递给 go 工具compile
hinzufügen.
go build -gcflags -m=1
Wenn Sie eine Ganzzahl größer als 1 übergeben, erhalten Sie eine ausführlichere Ausgabe. Wenn Sie damit nicht die Antworten erhalten, die Sie zur Optimierung Ihres Programms benötigen, versuchen Sie es mit Analyse. Es geht weit über die Gedächtnisanalyse hinaus.
Generell sollten Sie sich in Ihrer täglichen Arbeit nicht mit naiven Optimierungsentscheidungen herumschlagen. Hängen Sie sich nicht zu sehr auf „normalerweise …“ ein, denn in der realen Welt weiß man nie. Streben Sie immer zuerst eine Korrektheitsoptimierung an. Dann optimieren Sie die Leistung nur dann, wenn Sie sie wirklich brauchen, und beweisen Sie, dass Sie sie brauchen. Raten Sie nicht, glauben Sie nicht. Bedenken Sie außerdem, dass sich go ändert, sodass das, was wir in einer Version beweisen, nicht unbedingt auch in einer anderen zutrifft.
Das obige ist der detaillierte Inhalt vonZeigeroperationen und CPU-/Speichernutzung verstehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!