Wenn Ihr VPS mehrere Dienstanwendungen ausführt, eine davon jedoch manchmal alle Ressourcen beansprucht, sodass kein Zugriff auf den Server über SSH möglich ist. Sie wechseln zur Verwendung eines Kubernetes-Clusters und legen Grenzwerte für alle Anwendungen fest. Wir sahen dann, wie einige Anwendungen neu gestartet wurden, da der OOM-Killer das Problem des Speicherverlusts behoben hatte.
Natürlich ist OOM nicht immer ein Leckproblem, es kann auch eine Ressourcenüberschreitung sein. Leckageprobleme werden höchstwahrscheinlich durch Programmfehler verursacht. Das Thema, über das wir heute sprechen, ist, wie diese Situation so weit wie möglich vermieden werden kann.
Übermäßiger Ressourcenverbrauch schadet dem Geldbeutel, weshalb wir sofort handeln müssen.
Jetzt reden wir über Optimierung. Hoffentlich können Sie verstehen, warum wir nicht voreilig optimieren sollten!
Jetzt geben wir einige praktische Vorschläge gemäß der Standard-Entitätsklassifizierung in Go.
Versuchen Sie, den dritten Parameter zu verwenden: <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">make([]T, 0, len)</span>
make([]T, 0, len)
Wenn die genaue Anzahl der Elemente nicht bekannt ist und Das Slice ist von kurzer Dauer. Ja, Sie können eine größere Größe zuweisen, um sicherzustellen, dass das Slice während der Laufzeit nicht wächst.
Vergessen Sie nicht, das Kopieren zu verwenden.Versuchen Sie, beim Kopieren, z. B. beim Zusammenführen von zwei oder mehr Slices, nicht das Anhängen zu verwenden.
Korrekte IterationEin Slice mit vielen Elementen oder großen Elementen, verwenden Sie for, um ein einzelnes Element zu erhalten. Auf diese Weise werden unnötige Doppelarbeit vermieden.
Multiplexen von SlicesWenn eine Operation am eingehenden Slice ausgeführt wird und ein geändertes Ergebnis zurückgibt, können wir es zurückgeben. Dadurch wird eine neue Speicherzuweisung vermieden.
🎜Wenn Sie ein kleines Stück der Scheibe abschneiden und nur verwenden müssen, bleibt auch der Hauptteil der Scheibe erhalten. Der richtige Ansatz besteht darin, eine neue Kopie dieses kleinen Slice zu verwenden und den alten Slice an den GC zu übergeben.
Wenn das Zusammenfügen von Zeichenfolgen in einer Anweisung erfolgen kann, verwenden Sie <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">+</span>
操作符。如果需要在循环中执行此操作,使用 <span style="font-size: 15px;">string.Builder</span>
,并使用它的 <span style="font-size: 15px;">Grow</span>
方法预先指定 <span style="font-size: 15px;">Builder</span>
的大小,减少内存分配次数。
string 和 []byte 在底层结构上非常相近,有时这两种类型之间可以通过强转换来避免内存分配。
可以池化字符串,从而帮助编译器只存储一次相同的字符串。
我们可以使用 map(级联)而不是复合键,我们可以使用字节切片。尽量不使用 <span style="font-size: 15px;">fmt</span>
+ Operator. Wenn Sie dies in einer Schleife tun müssen, verwenden Sie
🎜string.Builder🎜
🎜 und verwenden Sie dessen 🎜🎜Grow🎜
🎜 Methode ist vorab angegeben🎜🎜Builder🎜
🎜 Größe, wodurch die Anzahl der Speicherzuweisungen reduziert wird. 🎜🎜🎜Konvertierungsoptimierung🎜🎜🎜String und []Byte sind in der zugrunde liegenden Struktur sehr ähnlich, und manchmal kann eine starke Konvertierung zwischen diesen beiden Typen verwendet werden, um eine Speicherzuweisung zu vermeiden. 🎜🎜🎜String-Resident🎜🎜🎜 kann Strings bündeln und so dem Compiler helfen, denselben String nur einmal zu speichern. 🎜🎜🎜Zuweisung vermeiden🎜🎜🎜Wir können Map (Kaskade) anstelle zusammengesetzter Schlüssel verwenden, wir können Byte-Slices verwenden. Versuchen Sie, 🎜🎜 fmt 🎜
🎜 Paket, da alle seine Methoden Reflektion verwenden. 🎜🎜Wir verstehen, dass kleine Strukturen nicht mehr als 4 Felder und nicht mehr als eine Maschinenwortgröße haben.
Einige typische Kopierszenarien
Dereferenzierung ist teuer und wir sollten es so wenig wie möglich tun, insbesondere in Schleifen. Außerdem geht die Möglichkeit verloren, schnelle Register zu verwenden.
Diese Arbeit ist vom Editor optimiert und daher günstig.
Wir können die Größe der Struktur selbst reduzieren, indem wir die Struktur ausrichten (in der richtigen Reihenfolge entsprechend der Größe der Felder anordnen).
Versuchen Sie, kleine Funktionen zu schreiben, die vom Compiler eingebunden werden können. Dies geht schneller, sogar schneller, als den Code selbst in die Funktion einzubetten. Dies gilt insbesondere für heiße Pfade.
Welche werden nicht inline sein
Versuchen Sie, kleine Parameter zu verwenden, da deren Replikation optimiert wird. Versuchen Sie, die Replikation und das Stapelwachstum bei der GC-Last im Gleichgewicht zu halten. Vermeiden Sie eine große Anzahl von Parametern und lassen Sie Ihr Programm schnelle Register verwenden (deren Anzahl ist begrenzt).
Dies scheint effizienter zu sein als die Deklaration dieser Variablen im Funktionskörper.
Helfen Sie dem Compiler, Ihren Code zu optimieren, speichern Sie die Zwischenergebnisse, und dann stehen Ihnen weitere Optionen zur Optimierung Ihres Codes zur Verfügung.
Versuchen Sie, die Verzögerung nicht zu verwenden, oder verwenden Sie sie zumindest nicht in einer Schleife.
Vermeiden Sie die Zuweisung von Speicher im Hot Path, insbesondere bei kurzlebigen Objekten. Machen Sie die häufigsten Zweige (wenn, wechseln)
Genau wie Slice, geben Sie beim Initialisieren der Map dessen Größe an.
struct{} ist nichts (beansprucht keinen Speicher), daher ist es sehr nützlich, es beispielsweise bei der Weitergabe von Signalen zu verwenden.
Karte kann nur wachsen, nicht schrumpfen. Wenn wir die Karte zurücksetzen müssen, hilft das Löschen aller ihrer Elemente nicht.
Wenn die Karte keine Zeiger enthält, verschwendet der GC keine wertvolle Zeit damit. Da auch Strings Zeiger verwenden, sollten Sie Byte-Arrays anstelle von Strings als Schlüssel verwenden.
Auch hier möchten wir keine Zeiger verwenden, sondern können eine Kombination aus Karte und Slice verwenden und die Schlüssel in der Karte und die Werte im Slice speichern. Auf diese Weise können wir den Wert ohne Einschränkungen ändern. 6. Schnittstelle Der Schlüssel liegt im Kopieren. Es stellt sich heraus, dass die Kosten für das Ein- und Auspacken der Schnittstelle ungefähr den Kosten für die Zuweisung der Strukturgröße entsprechen.
Vermeiden Sie Speicherzuweisungen.
Versuchen Sie wie anderswo auch, unnötige Zuweisungen zu vermeiden. Zum Beispiel eine Schnittstelle einer anderen zuweisen, anstatt zweimal zu boxen.Nur bei Bedarf verwenden
Vermeiden Sie die Verwendung von Schnittstellen in häufig aufgerufenen Funktionsparametern und Rückgabeergebnissen. Wir benötigen keine zusätzlichen Auspackvorgänge. Reduzieren Sie die Häufigkeit der Verwendung von Schnittstellenmethodenaufrufen, da dadurch Inlining verhindert wird.7. Pointer, Channels, Bounds Checks
Besonders in Schleifen, da es sich als zu teuer herausstellt. Dereferenzierung ist etwas, was wir nicht auf eigene Kosten tun wollen.
Die Kanalsynchronisierung ist langsamer als andere primitive Synchronisierungsmethoden. Darüber hinaus gilt: Je mehr Fälle ausgewählt werden, desto langsamer wird unser Programm. Select, Case und Default wurden jedoch optimiert.
Das ist auch teuer und wir sollten es vermeiden. Überprüfen (erhalten) Sie beispielsweise den maximalen Slice-Index nur einmal, nicht mehrmals. Versuchen Sie es am besten jetzt mit der extremen Option.
In diesem Artikel haben wir einige der gleichen Optimierungsregeln gesehen.
Helfen Sie dem Compiler, die richtige Entscheidung zu treffen, und er wird es Ihnen danken. Weisen Sie zur Kompilierungszeit Speicher zu, verwenden Sie Zwischenergebnisse und versuchen Sie, Ihren Code lesbar zu halten.
Ich betone noch einmal, dass für die implizite Optimierung Benchmarks obligatorisch sind. Wenn etwas, das gestern funktioniert hat, morgen nicht funktioniert, weil der Compiler zu schnell zwischen den Versionen wechselt und umgekehrt.
Vergessen Sie nicht, die integrierten Analyse- und Tracking-Tools von Go zu verwenden.
Das obige ist der detaillierte Inhalt vonGo: Einfache Optimierungshinweise. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!