2009-10-30 32 views
22

Lo que suelo hacer respecto al tamaño de heap de jvm es establecer el valor máximo muy alto para evitar la infame OutOfMemoryException.cómo elegir el tamaño del montón JVM?

Sin embargo, esta estrategia (o falta de estrategia) no parece ser realmente inteligente. :-).

Mi pregunta es cómo elegir los valores mínimos y máximos, y la diferencia entre los dos (¿el máximo-mínimo debe ser pequeño o grande?). Por ejemplo, desde here:

si el almacenamiento dinámico inicial es demasiado pequeño, el Java inicio de la aplicación se vuelve lento como la JVM se ve obligado a realizar recolección de basura con frecuencia hasta la pila ha crecido a un mayor tamaño razonable. Para un rendimiento de inicio óptimo , debe establecer el tamaño de almacenamiento inicial en el mismo tamaño de almacenamiento máximo de .

gracias.

Respuesta

18

Mi pregunta es cómo elegir el min y los valores máximo y la diferencia entre los dos (debe max-min ser pequeño o grande?)

Respuesta corta: Don 'supongo, perfila tu aplicación.

jconsole can give you useful high-level data como una sensación para el conjunto residente principal frente a los datos transitorios que normalmente asignamos y la recolección de basura. Lo que verá si mira la pestaña de la memoria de esa pantalla suele ser algo así como un diente de sierra. La esquina inferior de los dientes de sierra es alrededor de la que normalmente establecería el mínimo del montón, mientras que usaría el pico o la pendiente de los dientes de sierra para experimentar con un montón máximo. Si sus dientes son muy empinados, podría considerar un gran montón simplemente para retrasar la recolección de basura. Sin embargo, si no lo son, podría intentar un máximo de almacenamiento dinámico más pequeño para ver si eso podría dejar más recursos para otros procesos en su máquina (por ejemplo).

También debería considerar el server VM, ya que causará un comportamiento de recolección de basura diferente.

Dicho todo esto, también debe utilizar una herramienta más detallada como jvisualvm to profile the memory usage of your process. Es posible que tenga una fuga de memoria o un ambicioso asignador que pueda ajustar o eliminar. Eso cambiaría por completo sus necesidades de montón.

+0

Gracias por todas las referencias – LB40

+1

@LB, no hay problema. Literalmente uso esas herramientas todos los días. Citando a mí mismo: "No apestan". ;-) –

2

La respuesta correcta es: no hay una respuesta correcta cada proyecto es diferente y tendrá que ajustar su configuración de tamaño de montón por proyecto. Comenzaría pequeño y aumentaría gradualmente el tamaño del montón hasta que la aplicación se ejecute según lo previsto.

Tienes razón, establecer un gran valor máximo no es una buena idea.

+0

y existe alguna relación entre el tamaño mínimo y máximo? ¿O el tamaño de almacenamiento mínimo es completamente irrelevante? – LB40

+0

El min es * tipo de * irrelevante, sin duda si se asegura de que haya suficiente memoria física como para que las demandas de la JVM para el tamaño máximo de almacenamiento dinámico siempre se puedan acomodar.Yo diría que establezca el tamaño mínimo para el tipo de tamaño de almacenamiento dinámico que espera en el funcionamiento normal (para evitar que se vuelva a cambiar el tamaño varias veces al inicio), y el máximo debe reflejar una "zona de almacenamiento intermedio" por encima de esto. –

+0

No intento y adivino el SO/kernel. Tengo que asumir que tienen un buen manejo de la asignación de memoria, personalmente nunca he visto un problema perjudicial al hacer que la JVM se redimensione a sí misma y, literalmente, ignoro el parámetro -Xms casi del todo. – Xailor

5

Debe habilitar el registro de GC y comprobar para ver dónde está ocurriendo su OOM.

-verbose:gc 
-Xloggc:gc.log 
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDetails 

Usted puede estar experimentando los límites de espacio de permanente, ajuste a través de -XX:MaxPermSize=YYYm

De todos modos para responder a su pregunta, comienzo sin mínimos y establecer el máximo relativamente alto. Luego gráficas el registro de gc y descubro dónde está mi estado; visualmente elija un tamaño superior a la media para las distintas generaciones. Léelo como un cuadro financiero, querrá ver una buena distribución en las nuevas generaciones y un crecimiento y una recopilación constantes en la generación establecida. Como se mencionó, también grafica tu espacio permanente para asegurarte de que no estés aumentando constantemente.

La sintonización de GC es un arte, de ninguna manera una ciencia.

+2

"La afinación de GC es un arte, de ninguna manera una ciencia". Epic, voy a citarte ... – LB40

2

Si está experimentando un OOME, en realidad comenzaría por aumentar la memoria máxima tanto como pueda, y ver si eso resuelve el problema. Deje que su máquina absorba el problema de rendimiento, primero. Si el problema persiste, puede buscar diagnósticos de rendimiento para identificar los cuellos de botella y trabajar en aquellas áreas donde su aplicación podría tener fugas o podría estar acaparando la mayor cantidad de memoria.

Jeff Atwood tiene un buen artículo sobre CodingHorror que explica esta actitud; la solución más rentable para un problema de rendimiento es tirar de hardware (o en este caso, el aumento de los recursos de memoria) en el problema, antes de invertir tiempo de desarrollo en la resolución de problemas:

http://www.codinghorror.com/blog/archives/001198.html

3

De hecho, el establecimiento de una enorme máximo valorar ciegamente no es realmente una buena idea (medir, no adivinar) y esta estrategia conducirá a GCs "stop the world" muy largos que podrían no ser deseables desde el punto de vista de la experiencia del usuario (siempre tenga en cuenta que " cuanto más grande es el montón, más largo es el GC principal ").

Dicho esto, no hay una respuesta genérica a su pregunta, cada aplicación tiene diferentes necesidades. En realidad, sugeriría al perfil su aplicación y sintonizar el montón para encontrar un buen compromiso entre la frecuencia (principal) del GC y la (principal) duración del GC mientras se minimiza el tiempo de respuesta para el usuario final. Sugiero encarecidamente leer este gran blog post (y todos los demás) de Kirk Pepperdine para más detalles.

Solo para responder a la parte del valor mínimo y máximo, siempre uso los mismos valores (para un mejor rendimiento de inicio y una mejor reproducibilidad).

+0

El problema es que la huella de mi aplicación depende de la entrada. Entonces, perfilar es algo difícil – LB40

+0

@LB en cualquier aplicación dada (misma base de código), el perfil de uso puede ser muy diferente. Tengo que asesorar a todos mis clientes en la situación posterior a la puesta en marcha para el ajuste de JVM como parte de una mayor fase de optimización y creación de perfiles a medida que cambia de cliente a cliente, usuarios por usuario. – Xailor

+0

¿Por qué, no lo entiendo? ¿Cómo se ve la entrada del usuario para el 80% de los usuarios? –

2

Es una muy mala idea "ignorar el parámetro -Xms" ya que generalmente hay otras aplicaciones y procesos ejecutándose en el mismo cuadro. Desea que su aplicación se inicie con la cantidad máxima de RAM asignada, por lo que si falla, falla mientras mira los registros de inicio, y no a las 4:00 AM cuando otra aplicación ha ocupado RAM adicional en la caja, y su JVM no puede crecer de tamaño.

En resumen, SIEMPRE configure JVM min y mezcle el tamaño con el mismo valor.

Cuestiones relacionadas