Haben Sie eine Speicherzuweisungsfrage, mit der ich Ihre Hilfe haben möchte. Wir haben einige unserer Dienste im oberen Bereich analysiert, und wir haben festgestellt, dass sie einen RES-Wert von etwa 1,8 GB haben, was, soweit ich weiß, bedeutet, dass sie zu diesem Zeitpunkt 1,8 GB Speicher behalten. Was wäre in Ordnung, wenn wir sie gerade erst gestartet hätten (sie lesen im Wesentlichen aus einem Cache, machen die Verarbeitung und schieben in einen anderen Cache), aber wenn wir sehen, dass dies nach der CPU-intensiven Verarbeitung noch abgeschlossen ist, fragen wir uns bedeutet, dass etwas nicht wie erwartet erwartet wird.
Wir führen das Programm mit den folgenden Parametern aus: -Xms256m -Xmx3096m was, wie ich es verstehe, eine anfängliche Heap-Größe von 256 und eine maximale Heap-Größe von 3096 bedeutet.
Nun, was ich erwarten würde zu sehen, ist der Heap, der anfangs wie benötigt wächst und dann nach Bedarf verkleinert wird, wenn der Speicher freigegeben wird (obwohl dies mein erster Fehler sein könnte). Was wir tatsächlich mit jvisualvm sehen, ist folgendes:
Meine Frage wäre, warum ist mein Haufen nicht geschrumpft, wie ich es vielleicht erwartet hatte? Stört das nicht andere Prozesse auf der Linux-Box mit wertvollem Speicher, und wenn ja, wie könnte ich das beheben? Wir sehen manchmal nicht genügend Speicherfehler, und da diese Prozesse die "unerwartetste" Speichergröße zugewiesen bekommen, dachte ich, dass es am besten ist, mit ihnen zu beginnen.
Prost, Dave.
(~ bitte entschuldigen Sie mögliche Unverständnis beim JVM-Speicher-Tuning!)
Vielleicht möchten Sie sehen diese Antwort zum Anpassen der Heap-Erweiterung und Schrumpfung. Standardmäßig ist die JVM nicht zu aggressiv beim Schrumpfen des Heapspeichers. Außerdem, wenn der Heap genügend freien Speicherplatz für einen langen Zeitraum hat, wird er keinen GC auslösen, was meiner Meinung nach der einzige Zeitpunkt ist, den es zu verkleinern gilt.
Idealerweise konfigurieren Sie das Maximum auf einen Wert, der Ihrer Anwendung unter voller Last genügend Headroom zur Verfügung stellt, ist jedoch akzeptabel für die Betriebssystemleistung, wenn sie immer in Verwendung war. Es ist nicht ungewöhnlich, das Minimum für Vorhersehbarkeit und potenziell bessere Leistung auf das Maximum zu setzen (ich habe dafür nichts zu tun).
Ich habe keine vollständige Antwort, aber eine ähnliche Frage ist gekommen vor . Aus der vorherigen Diskussion sollten Sie -XX:MaxHeapFreeRatio=
als Ihren Optimierungsparameter untersuchen, um die Heap-Freigabe zurück zum Betriebssystem zu erzwingen. Es gibt eine Dokumentation hier , und ich glaube, dass der Standardwert sehr groß ist Menge des unbenutzten Heap zu bleiben im Besitz der JVM.
Nun, der GC läuft nicht immer wenn du denkst und sammelt nicht immer was auslösbar ist. Es könnte auch nur beginnen, Objekte aus dem alten Gen-Raum zu sammeln, wenn es fast keinen Heap-Platz mehr hat (da das Sammeln von altem Gen normalerweise eine Stop-the-world-Sammlung beinhaltet, die der GC zu vermeiden versucht, bis es wirklich benötigt wird es).
Vielleicht könntest du ein Profiling mit TPTP, visualvm oder JProbe (kommerziell, aber Testversion) versuchen, um herauszufinden, was genau passiert.
Eine andere Sache, auf die Sie achten sollten, sind Dateihandler; Ich habe nicht die Details, aber einer meiner Kollegen stieß vor ein paar Jahren auf ein Heap-Sättigungsproblem, verursacht durch einen Prozess, der viele Dateien öffnete und herausfand, dass jedes Mal, wenn er einen öffnete, ein 4kb-Puffer im nativen Heap zugewiesen wurde. am Ende der Verarbeitung freigegeben. Ich hoffe, dass diese recht vagen Hinweise helfen können ...