Speicherverschwendung durch Spring-Boot-Anwendung

Eine der weithin verschwendeten Ressourcen in der heutigen Welt ist: Erinnerung. Aufgrund ineffizienter Programmierung wird eine überraschende (manchmal „schockierende“) Menge an Speicher verschwendet. Dieses Muster wiederholt sich in mehreren Unternehmensanwendungen. Um diesen Fall zu beweisen, haben wir eine kleine Studie durchgeführt. Wir haben die berühmte Spring Boot Pet Clinic-Anwendung analysiert, um zu sehen, wie viel Speicher sie verschwendet. Diese Anwendung wurde von der Community entwickelt, um zu zeigen, wie das Spring Application Framework verwendet werden kann, um einfache, aber leistungsstarke datenbankorientierte Anwendungen zu erstellen.

Umfeld
Spring Boot 2.1.4.RELEASE
Java-SDK 1.8
Kater 8.5.20
MySQL 5.7.26 mit MySQL Connector/J 8.0.15

Stresstest
Wir haben Apache JMeter verwendet, ein beliebtes Open-Source-Lasttesttool, um unseren Stresstest durchzuführen. Wir haben den Belastungstest für 30 Minuten mit den folgenden Einstellungen durchgeführt:

Anzahl der Threads (Benutzer) – 1000 (Anzahl der Benutzer, die sich mit dem Ziel verbinden)
Hochlaufzeit (in Sekunden) – 10. Der Zeitrahmen für den Start aller Anfragen. Gemäß unserer Konfiguration wird alle 0,01 Sekunden 1 neuer Thread gestartet, dh 100 Threads/Sekunde.
Schleifenanzahl – Bis in alle Ewigkeit. Diese 1000 Threads führen nacheinander Testiterationen durch.
Dauer (Sekunden) -1800. Nach dem Hochfahren laufen 1000 Threads kontinuierlich für 1800 Sekunden.
Capture.PNG
Abb: Jmeter-Einstellungen

In unserem Lasttest haben wir folgende Szenarien durchgespielt:

* Fügen Sie dem System einen neuen Haustierbesitzer hinzu.
*Informationen zu einem Haustierbesitzer anzeigen.
* Fügen Sie einem System ein neues Haustier hinzu.
*Informationen zu einem Haustier anzeigen.
* Fügen Sie Informationen zu einem Besuch zum Besuchsverlauf eines Haustieres hinzu.
*Aktualisieren Sie die Informationen zu einem Haustier.
*Aktualisieren Sie die Informationen zu einem Haustierbesitzer.
*Besitzerinformationen anzeigen, indem Sie nach seinem Namen suchen.
*Informationen aller Eigentümer anzeigen.

Wie misst man Speicherverschwendung?
Die Industrie verfügt über Hunderte von Tools, um die verwendete Speichermenge anzuzeigen. Aber selten stoßen wir auf Tools, die die Menge an Speicher messen können, die durch ineffiziente Programmierung verschwendet wird. HeapHero ist ein einfaches Tool, das Ihre Heap-Dumps analysiert und angibt, wie viel Speicher aufgrund ineffizienter Programmierung verschwendet wird.

Wir haben den Heap-Dump aus der Spring Boot Pet Clinic-Anwendung erfasst, als der Test ausgeführt wurde. (es gibt 7 verschiedene Optionen zum Erfassen von Heap-Dumps von Java/Android-Anwendungen. Sie können die Option wählen, die für Sie bequem ist).

Wir haben den erfassten Heap-Dump in das HeapHero-Tool hochgeladen. Das Tool hat diesen schönen Bericht erstellt, der zeigt, dass 65 % des Speichers aufgrund ineffizienter Programmierung verschwendet werden. Ja, dies ist eine einfache Vanilla-Anwendung, in der alle Best Practices implementiert sein sollen, die auch auf einem hochgelobten Framework 65 % des Speichers verschwendet.

Die Industrie verfügt über Hunderte von Tools, um die verwendete Speichermenge anzuzeigen. Aber selten stoßen wir auf Tools, die die Menge an Speicher messen können, die durch ineffiziente Programmierung verschwendet wird. HeapHero ist ein einfaches Tool, das Ihre Heap-Dumps analysiert und angibt, wie viel Speicher aufgrund ineffizienter Programmierung verschwendet wird.

Wir haben den Heap-Dump aus der Spring Boot Pet Clinic-Anwendung erfasst, als der Test ausgeführt wurde. (Es gibt 7 verschiedene Optionen zum Erfassen von Heap-Dumps von Java-/Android-Anwendungen. Sie können die Option auswählen, die für Sie am bequemsten ist).

Wir haben den erfassten Heap-Dump in das HeapHero-Tool hochgeladen. Das Tool hat diesen schönen Bericht erstellt, der zeigt, dass 65 % des Speichers aufgrund ineffizienter Programmierung verschwendet werden. Ja, dies ist eine einfache Vanilla-Anwendung, in der alle Best Practices implementiert sein sollen, die auch auf einem hochgelobten Framework 65 % des Speichers verschwendet.

![pie-chart.PNG](Abb.: Von HeapHero erstelltes Diagramm, das zeigt, dass 65 % des Arbeitsspeichers durch die Spring Boot-Anwendung für Tierkliniken verschwendet werden

Speicherverschwendung analysieren
Aus dem Bericht können Sie Folgendes entnehmen:

15,6 % des Speichers werden durch doppelte Zeichenfolgen verschwendet
14,6 % des Arbeitsspeichers werden durch ineffiziente primitive Arrays verschwendet
14,3 % des Arbeitsspeichers werden durch doppelte primitive Arrays verschwendet
12,1 % des Arbeitsspeichers werden durch ineffiziente Sammlungen verschwendet

Doppelte Zeichenfolgen
Der Hauptgrund für die Speicherverschwendung in dieser Spring-Boot-Anwendung (und in den meisten Unternehmensanwendungen) ist: Duplizieren von Zeichenfolgen. Der Bericht zeigt, wie viel Speicher durch Duplikate von Strings verschwendet wird, um welche Strings es sich handelt, wer sie erstellt und wie man sie optimiert.

doppelte Zeichenfolgen.PNG
Abb.: Doppelte Saiten

Sie können feststellen, dass 15,6 % des Speichers aufgrund doppelter Zeichenfolgen verschwendet werden. bitte beachten Sie

Der String von Goldi wurde 207.481 Mal erstellt.
Die Zeichenfolge „Besuch“ wurde 132.308 Mal erstellt. „Besuch“ war die Beschreibung, die wir im Testskript erwähnt haben.
Der String „Bangalore“ wurde 75.374 Mal erstellt. „Banglore“ ist der Name der Stadt, die wir im Testskript angegeben haben.
„123123123“ wurde 37.687 Mal erstellt.
Die Zeichenfolge „Mahesh“ wurde 37.687 Mal erstellt.
Anscheinend ist „Goldi“ der Name des Haustiers, der durch das Testskript auf dem Bildschirm eingegeben wurde. „Besuch“ war die Beschreibung, die über das Testskript auf dem Bildschirm eingegeben wurde. Ähnlich sind die Werte. Aber die Frage, warum so viele tausend Mal dieselben String-Objekte erstellt werden.

Wir alle wissen, dass Strings unveränderlich sind (dh wenn sie einmal erstellt wurden, können sie nicht mehr geändert werden). In Anbetracht dessen, warum diese vielen Tausend doppelten Zeichenfolgen erstellt werden?

Das HeapHero-Tool meldet auch den Codepfad, in dem diese doppelten Zeichenfolgen erstellt werden.

doppelte-strings-holding.PNG
Abb.: Codepfad, von dem doppelte Zeichenfolgen stammen

Hier sind die Empfehlungen auf hohem Niveau um doppelte Zeichenfolgen in Ihrer Anwendung zu beheben. Sie können die Strategien anwenden, die auf Ihre Anwendung anwendbar sind.

Ineffiziente Sammlungen
Ein weiterer Hauptgrund für die Speicherverschwendung in der Anwendung Spring Boot Pet Clinic ist: ineffiziente Implementierung der Sammlungen. Nachfolgend der Auszug aus dem HeapHero-Bericht:

ineffiziente Sammlungen.PNG
Abb.: Speicherverschwendung durch ineffiziente Sammlungen

Sie können feststellen, dass 99 % von LinkedHashSet im Speicher keine Elemente enthalten. Wenn es keine Elemente gibt, warum dann überhaupt LinkedHashSet erstellen? Wenn Sie ein neues LinkedHashSet-Objekt erstellen, wird Platz für 16 Elemente im Speicher reserviert. Der gesamte Platz, der für diese 16 Elemente reserviert ist, wird jetzt verschwendet. Wenn Sie das LinedHashset faul initialisieren, tritt dieses Problem nicht auf.

Schlechte Praxis:

private LinkedHashSet<String, String> myHashSet = new LinkedHashSet();

public void addData(String key, String value) {

 myHashSet.put(key, value);
}

Beste Übung:

private LinkedHashSet<String, String> myHashSet;

public void addData(String key, String value) {

      if (myHashSet == null) {

 myHashSet = new LinkedHashSet();
      }

myHashSet.put(key, value);
}

Ähnlich ist eine andere Beobachtung: 68 % von ArrayList enthalten nur 1 Element in sich. Wenn Sie ein ArrayList-Objekt erstellen, wird Platz für 10 Elemente im Speicher reserviert. Dies bedeutet, dass in 88% der ArrayList 9-Elemente Speicherplatz verschwendet wird. Wenn Sie ArrayList mit Kapazität initialisieren können, kann dieses Problem vermieden werden.

Schlechte Praxis: Initialisieren von Sammlungen mit Standard.

new ArrayList();

Best Practice: Sammlungen mit Kapazität initialisieren

 new ArrayList(1);

Speicher ist nicht billig
Man kann argumentieren, dass Speicher so billig ist, warum muss ich mir also Sorgen machen? Faire Frage. Aber das Gedächtnis meiner Freunde ist im Cloud-Computing-Zeitalter nicht billig. Es gibt 4 primäre Rechenressourcen:
*ZENTRALPROZESSOR
*Erinnerung
*Netzwerk
*Lagerung

Ihre Anwendung wird möglicherweise auf Zehntausenden von Anwendungsservern ausgeführt, die auf AWS EC2-Instanzen ausgeführt werden. Welche der oben genannten 4 Rechenressourcen wird in einer EC2-Instance ausgelastet? Ich bitte Sie, hier kurz innezuhalten, bevor Sie weiterlesen. Denken Sie darüber nach, welche Ressource zuerst gesättigt ist.

Für die meisten Anwendungen ist es das Erinnerung. CPU ist immer bei 30 – 60%. Es gibt immer reichlich Stauraum. Es ist schwierig, das Netzwerk zu sättigen (es sei denn, Ihre Anwendung streamt viele Videoinhalte). Daher ist es bei den meisten Anwendungen der Speicher, der zuerst gesättigt wird. Obwohl CPU, Speicher und Netzwerk nicht ausgelastet sind, stellen Sie am Ende immer mehr EC2-Instanzen bereit, nur weil der Arbeitsspeicher gesättigt ist. Dies erhöht Ihre Rechenkosten um ein Vielfaches.

Andererseits verschwenden moderne Anwendungen ausnahmslos zwischen 30 und 90 % des Arbeitsspeichers aufgrund ineffizienter Programmierpraktiken. Selbst über Spring Boot Pet Clinic ohne viel Geschäftslogik werden 65 % des Speichers verschwendet. Echte Unternehmensanwendungen werden in ähnlicher Größenordnung oder sogar noch viel mehr verschwenden. Wenn Sie also speichereffizienten Code schreiben können, werden Ihre Rechenkosten gesenkt. Da Speicher die erste Ressource ist, die gesättigt ist, könnten Sie Ihre Anwendung auf einer kleineren Anzahl von Serverinstanzen ausführen, wenn Sie den Speicherverbrauch reduzieren können. Möglicherweise können Sie 30 – 40 % der Server reduzieren. Das bedeutet, dass Ihr Management 30 – 40 % der Kosten für Rechenzentren (oder Cloud-Hosting-Anbieter) zuzüglich Wartungs- und Supportkosten reduzieren kann. Es kann mehrere Millionen/Milliarden Dollar an Kosteneinsparungen ausmachen.

Fazit
Neben der Reduzierung der Rechenkosten wird Ihr Kundenerlebnis auch viel besser, wenn speichereffizienter Code geschrieben wird. Wenn Sie die Anzahl der Objekte reduzieren können, die zum Bedienen neuer eingehender Anforderungen erstellt werden, wird Ihre Antwortzeit viel besser. Da weniger Objekte erstellt werden, werden weniger CPU-Zyklen für deren Erstellung und Garbage Collection aufgewendet. Die Reduzierung der Reaktionszeit führt zu einem besseren Kundenerlebnis.

Similar Posts

Leave a Reply

Your email address will not be published.