Wie kann man die Spring Boot-Speichernutzung reduzieren?

Lesezeit: 5 Minuten

Benutzeravatar von Hailong Li
Hailong Li

Ich verwende Spring Boot, um eine Client-Anwendung zu entwickeln. und wenn Sie die Spring Boot-Anwendung ausführen (mit einem vollständig ausführbaren JAR), beträgt die Speichernutzung etwa 190 MB auf einem x64-Server und 110 MB auf einem x86-Server.

Meine JVM-Optionen sind (-Xmx64M -Xms64M -XX:MaxPermSize=64M -server), warum ist die Speichernutzung auf dem x64-Server so groß? Wie kann die Speichernutzung auf unter 150 MB reduziert werden?

Danke.

  • x64-Zeiger (64-Bit) sind doppelt so groß wie x86-Zeiger (32-Bit), sodass die Speichernutzung im 64-Bit-Modus zwangsläufig größer ist.

    –Andreas

    12. Juni 2017 um 4:27 Uhr

  • ja, aber ich weiß nicht, welcher Speicher außer Heap + Perm verwendet wird. Ich habe die maximale Heap-Größe auf 64 MB und die maximale Perm-Größe auf 64 MB eingestellt, aber warum werden ungefähr 60 MB (190 MB – 64 MB x 2) verwendet, und ich kann sie nicht reduzieren.

    – Hailong Li

    12. Juni 2017 um 5:26 Uhr


  • @ HailongLi Sie haben erwähnt, was zu einer Erhöhung des Speichers führt. Aber wie kann man es reduzieren?

    – Krisch

    12. Mai 2018 um 9:33 Uhr

  • Etwas später, aber dieser Beitrag kann helfen dzone.com/articles/…

    – Sigrist

    21. September 2018 um 14:35 Uhr

Benutzeravatar von CCob
CCob

Etwas spät zum Spiel hier, aber ich hatte das gleiche Problem mit einer containerisierten Spring Boot-Anwendung auf Docker. Das absolute Minimum, mit dem Sie davonkommen, ist etwa 72 MB Gesamtspeicher bei den einfachsten Spring Boot-Anwendungen mit einem einzigen Controller und eingebettetem Tomcat. Fügen Sie Spring Data REST, Spring Security und ein paar JPA-Einheiten hinzu, und Sie werden mindestens 200 Mio. bis 300 Mio. sehen. Mit den folgenden JVM-Optionen können Sie eine einfache Spring Boot-App auf insgesamt etwa 72 MB reduzieren.

Mit -XX:+UseSerialGC Dadurch wird die Garbage Collection inline mit dem Thread durchgeführt, der den Heap-Speicher anstelle eines dedizierten GC-Threads zuweist.

Mit -Xss512k Dadurch wird der Stack-Speicher jedes Threads auf 512 KB anstelle der Standardeinstellung von 1 MB begrenzt

Mit -XX:MaxRAM=72m Dadurch werden die Berechnungen der JVM für den Heap- und Nicht-Heap-verwalteten Speicher so eingeschränkt, dass sie innerhalb der Grenzen dieses Werts liegen.

Zusätzlich zu den oben genannten JVM-Optionen können Sie auch die folgende Eigenschaft in Ihrer verwenden application.properties Datei:

server.tomcat.max-threads = 1 Dadurch wird die Anzahl der HTTP-Request-Handler-Threads auf 1 begrenzt (Standard ist 200).


Hier ist ein Beispiel für docker stats laufen a sehr einfache Spring Boot-Anwendung mit den oben genannten Grenzen und mit dem Docker -m 72m Streit. Wenn ich die Werte weiter verringere, kann die App nicht gestartet werden.

83ccc9b2156d: Mem Usage: 70.36MiB / 72MiB | Mem Percentage: 97.72%

Und hier sehen Sie eine Aufschlüsselung des gesamten nativen und Java-Heap-Speichers beim Beenden.

Native Memory Tracking:

Total: reserved=1398681KB, committed=112996KB
-                 Java Heap (reserved=36864KB, committed=36260KB)
                            (mmap: reserved=36864KB, committed=36260KB) 

-                     Class (reserved=1086709KB, committed=43381KB)
                            (classes #7548)
                            (  instance classes #7049, array classes #499)
                            (malloc=1269KB #19354) 
                            (mmap: reserved=1085440KB, committed=42112KB) 
                            (  Metadata:   )
                            (    reserved=36864KB, committed=36864KB)
                            (    used=36161KB)
                            (    free=703KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=1048576KB, committed=5248KB)
                            (    used=4801KB)
                            (    free=447KB)
                            (    waste=0KB =0.00%)

-                    Thread (reserved=9319KB, committed=938KB)
                            (thread #14)
                            (stack: reserved=9253KB, committed=872KB)
                            (malloc=50KB #74) 
                            (arena=16KB #26)

-                      Code (reserved=248678KB, committed=15310KB)
                            (malloc=990KB #4592) 
                            (mmap: reserved=247688KB, committed=14320KB) 

-                        GC (reserved=400KB, committed=396KB)
                            (malloc=272KB #874) 
                            (mmap: reserved=128KB, committed=124KB) 

-                  Compiler (reserved=276KB, committed=276KB)
                            (malloc=17KB #409) 
                            (arena=260KB #6)

-                  Internal (reserved=660KB, committed=660KB)
                            (malloc=620KB #1880) 
                            (mmap: reserved=40KB, committed=40KB) 

-                    Symbol (reserved=11174KB, committed=11174KB)
                            (malloc=8417KB #88784) 
                            (arena=2757KB #1)

-    Native Memory Tracking (reserved=1858KB, committed=1858KB)
                            (malloc=6KB #80) 
                            (tracking overhead=1852KB)

-               Arena Chunk (reserved=2583KB, committed=2583KB)
                            (malloc=2583KB) 

-                   Logging (reserved=4KB, committed=4KB)
                            (malloc=4KB #179) 

-                 Arguments (reserved=17KB, committed=17KB)
                            (malloc=17KB #470) 

-                    Module (reserved=137KB, committed=137KB)
                            (malloc=137KB #1616)

Erwarten Sie auch keine anständige Leistung, da ich mir vorstellen kann, dass der GC mit diesem Setup häufig ausgeführt wird, da er nicht viel freien Speicher zum Spielen hat

  • Lebensretter im Jahr 2020 mit dem -XX:MaxRAM Einstellung für meinen Heroku-Dyno, der ständig R14-Fehler auslöst

    – kmek

    17. April 2020 um 6:23 Uhr

  • 72MB?! Ha!! Ja richtig, meine App beginnt bei 950MB. Spring Boot 2.3.0, nichts weiter als ein paar REST-Controller. Es dauert weniger als 10 Sekunden, um zu starten, aber selbst ohne Anfragen zu erhalten, ohne es zu belasten, schießt es auf 1 GB hoch und bleibt dort.

    – JeneralJames

    14. Dezember 2020 um 9:34 Uhr

  • @JeneralJames Genau das passiert mir in der Produktion. Und ich habe zunehmend das Gefühl, dass dies nicht die Technologie für eine containerisierte Welt ist. Dies ist wirklich für monolithische Anwendungsserver und Hunderte von Endpunkten (Controller) gemacht. Aus diesem Grund kommen neuere Technologien im Java-Bereich wie Quarkus auf, um genau dieses Problem anzugehen. Noch bessere Plattformen wie Node/Go/.net Core, die für Cloud-/Container-native Archs entwickelt wurden.

    – shakeel osmani

    28. Februar 2021 um 20:22 Uhr

Benutzeravatar von Hailong Li
Hailong Li

Nach der Suche habe ich festgestellt, dass es bereits eine Antwort in Stackoveflow gibt. Der Spring Boot-Speicherverbrauch steigt über die Option -Xmx hinaus

1. Number of http threads (Undertow starts around 50 threads per default, but you can increase / decrease via property the amount of threads needed)
2. Access to native routines (.dll, .so) via JNI
3. Static variables
4. Use of cache (memcache, ehcache, etc)
If a VM is 32 bit or 64 bit, 64 bit uses more memory to run the same application, so if you don't need a heap bigger than 1.5GB, so keep your application runnnig over 32 bit to save memory.

weil Spring Boot standardmäßig etwa 50 Threads für den HTTP-Dienst (Tomcat oder Undertow, Jetty) startet und 1 MB pro Thread verwendet (64-Bit-JVM-Standardeinstellung).

SO beträgt die Speichernutzung in 64-Bit-JVM Heap (64 MB) + Permgen (max. 64 MB) + Thread-Stacks (1 MB x 50+) + native Handles.

Verweise:

  • Wie kann man diese Speichergröße reduzieren? Liegt es an dem in die JAR-Datei eingebetteten Tomcat-Server? Wenn wir es als Kriegsdatei ausführen, wird der Speicher reduziert?

    – Krisch

    11. Mai 2018 um 18:31 Uhr

  • Diese akzeptierte Antwort beantwortet die Frage nicht. Die Frage war, wie der Speicherverbrauch reduziert werden kann, nicht zu erklären, warum viel Speicher verwendet wird.

    – Michael

    24. Juli 2018 um 18:30 Uhr

  • warum hat das 5 Upvotes? es beantwortet die Frage nur teilweise

    – phil294

    22. August 2018 um 12:34 Uhr

  • Zu verstehen, warum etwas passiert, hilft bei der Lösung des Problems. Beide Antworten sind gut, die eine geht in winzige Details, während die andere einen Überblick gibt. Sie ergänzen sich gegenseitig.

    – Tinus Tate

    6. November 2018 um 19:18 Uhr


Sie können -XX:+UseSerialGC als JVM-Argument verwenden, um den Serial Garbage Collector anzugeben, der die beste Wahl zum Reduzieren von Memory Heap ist.

1444440cookie-checkWie kann man die Spring Boot-Speichernutzung reduzieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy