2010-05-27 10 views
42

En Java, el modo concurrente falla significa que el colector concurrente no pudo liberar suficiente espacio de memoria de forma permanente y permanente y debe abandonar y dejar por completo. -world gc entra en acción. El resultado final puede ser muy caro.Cómo reducir el modo simultáneo de Java y el exceso de gc

que entender este concepto, pero nunca tuvo una buena comprensión global de
A) lo que podría ocasionar un fallo del modo concurrente y
B) ¿cuál es la solución ?.

Este tipo de falta de claridad me lleva a escribir/depurar código sin muchos consejos en mente y, a menudo, tengo que comparar esos indicadores de rendimiento de Foo a Bar sin motivos particulares, solo tengo que intentarlo.

Me gustaría aprender de los desarrolladores aquí cómo es su experiencia? Si se había encontrado con un problema de rendimiento, ¿cuál fue la causa y cómo lo resolvió?

Si tiene recomendaciones de codificación, no sea demasiado general. ¡Gracias!

+0

¿De verdad ha experimentado un fallo de modo concurrente? – Justin

+4

Lo hice, honestamente, con bastante frecuencia. p.ej. 295285.052: [GC 295285.052: [ParNew: 197658K-> 197658K (245760K), 0.0000290 segundos] 295285.052: [CMS295286.188: [CMS-concurrent-mark: 3.109/3.348 segundos] [Tiempos: usuario = 6.12 sys = 0.88, real = 3,35 segundos] (error de modo simultáneo): 936976K-> 904898K (962560K), 5,3725960 segundos] 1161866072K-> 926615760K (1237319680K), [CMS Perm: 97908K-> 97897K (131072K)], 5,3729920 segundos] [Tiempos: usuario = 5,36 sys = 0,00, real = 5,37 segundos]. A veces, OOM es bastante rápido y es asesinado, a veces sufre un largo período de GC (la última vez fue más de 10 horas). – jimx

+0

¿Ha agregado algunas configuraciones de gc cuando ejecuta Java? En caso afirmativo, ¿cuáles son esas? – Inv3r53

Respuesta

3

A veces OOM bastante rápido y se mató, en algún momento sufre un largo período de GC (la última vez fue más de 10 horas).

Me parece que una fuga de memoria está en la raíz de sus problemas.

Una falla de CMS no causará (según tengo entendido) un OOM. Más bien ocurre una falla de CMS porque la JVM necesita hacer demasiadas colecciones demasiado rápido, y CMS no pudo mantener el ritmo. Una situación en la que ocurren muchos ciclos de recolección en un período corto es cuando su pila está casi llena.

El tiempo de GC realmente largo suena raro ... pero es teóricamente posible si su máquina se agitaba horriblemente. Sin embargo, un largo período de repetidos GC es bastante plausible si su montón está casi lleno.

Puede configurar el GC para que abandone cuando el montón es 1) en el tamaño máximo y 2) sigue estando casi lleno después de que se haya completado un GC completo. Intenta hacer esto si aún no lo has hecho. No resolverá sus problemas, pero al menos su JVM obtendrá el OOM rápidamente, lo que permite un servicio más rápido de reinicio y recuperación.

EDITAR - la opción de hacerlo es -XX:GCHeapFreeLimit=nnn donde nnn es un número entre 0 y 100 dando el porcentaje mínimo del dinámico que debe quedar libre después de la GC. El valor predeterminado es 2. La opción se enumera en la página acertadamente titulada "The most complete list of -XX options for Java 6 JVM". (Hay muchas opciones de -XX enumeradas allí que no aparecen en la documentación de Sun. Desafortunadamente, la página proporciona pocos detalles sobre lo que realmente hacen las opciones.)

Probablemente debería comenzar a buscar para ver si su aplicación/webapp tiene pérdidas de memoria. Si es así, tus problemas no desaparecerán a menos que se encuentren y reparen esas fugas. A largo plazo, juguetear con las opciones de Hotspot GC no solucionará las pérdidas de memoria.

+0

Entendido. Sabía que hay una fuga lenta en nuestro programa, todavía podemos encontrarla. :(Mientras tanto, estábamos tratando de exprimir todo lo posible para ver si las diferentes políticas de gc pueden ayudar a mitigar el problema. CMS no causaría directamente el OOM, pero a menudo con todo el gc se activa y eso puede causar Problemas importantes: a menudo vemos que el rendimiento comienza a degradarse cuando aparece el error del modo CMS en nuestro registro de gc. Pero tal vez la falta de experiencia, todavía no hemos podido encontrar la fuga o encontrar la política de GC adecuada que encaje bien. – jimx

+0

Siento ese montón completo no necesariamente significa que habrá un grave problema de gc pero no poder recolectar gran cantidad de basura después de que un gc completo es realmente una mala señal. Si quisiera pedirle a jvm que mate la aplicación lo más pronto posible, qué banderas debería usar un reinicio más rápido del servicio y la recuperación suena prometedora. Al menos no tenemos que sufrir una gran falta de respuesta. Preferiría elegir morir rápido. Gracias. – jimx

11

Citado de "Understanding Concurrent Mark Sweep Garbage Collector Logs"

El fallo del modo concurrente puede o bien evitarse aumentando el tamaño generación tenured o iniciar la colección de CMS en una ocupación montón menor configurando CMSInitiatingOccupancyFraction a un valor inferior

Sin embargo, si realmente hay una pérdida de memoria en su aplicación, solo está comprando ti yo.

Si necesita reiniciar y recuperar rápidamente y prefiere un enfoque 'morir rápido', le sugiero que no use CMS en absoluto. Me quedaría con '-XX: + UseParallelGC'.

De "Garbage Collector Ergonomics"

El recolector de basura paralelo (UseParallelGC) tiros un excepción fuera de la memoria si un cantidad excesiva de tiempo está siendo pasó recoger una pequeña cantidad de la montón. Para evitar esta excepción, puede aumentar el tamaño del montón. Puede también establecer los parámetros -XX:GCTimeLimit=time-limit y -XX:GCHeapFreeLimit=space-limit

+0

CMSInitiarOccupancyFraction fue lo que había intentado. Parece que no es una buena idea para nuestra situación ion. Prefiero comprar rápido morir. – jimx

+0

Aunque todavía no sé si quiero hacer el cambio a ParallelGC. Nuestra experiencia previa parece indicar que la larga pausa fue causada principalmente por la falla del CMS y se activa la gc completa. Esos gcs completos consecutivos son realmente los culpables. Estaba tratando de averiguar si hay una manera de permanecer en el CMS, pero cuando el exceso de gc completo toma demasiado tiempo, mátalo. ¿Seguirán funcionando GCTimeLimit y GCHeapFreeLimit en CMS? – jimx

+0

Supongo que GCTimeLimit y GCHeapFreeLimit son solo para algoritmos paralelos. Hasta que se descubra la fuga de memoria, generalmente practicamos un "restablecimiento de la cordura" periódico de la JVM en una ventana de tiempo acordada con el usuario. – fglez

19

La primera cosa sobre CMS que he aprendido es que necesita más memoria que los otros colectores, alrededor de 25 a 50% más es un buen punto de partida. Esto le ayuda a evitar la fragmentación, ya que CMS no hace ninguna compactación como la parada que los coleccionistas del mundo harían. Segundo, haz cosas que ayuden al recolector de basura; Integer.valueOf en lugar de nuevo Integer, elimine las clases anónimas, asegúrese de que las clases internas no accedan a cosas inaccesibles (privadas en la clase externa) cosas así. Cuanto menos basura, mejor. FindBugs y no ignorar las advertencias ayudarán mucho con esto.

En cuanto a afinación, he encontrado que hay que probar varias cosas:

-XX: + UseConcMarkSweepGC

Le dice JVM utilizar CMS en titular gen.

Arregle el tamaño de su pila: -Xmx2048m -Xms2048m Esto evita que GC tenga que hacer cosas como crecer y reducir el montón.

-XX: + UseParNewGC

uso paralelo en lugar de recogida de serie en la generación joven. Esto acelerará tus colecciones menores, especialmente si tienes configurado un gen joven muy grande. Una gran generación joven generalmente es buena, pero no va más de la mitad del tamaño de la vieja generación.

-XX: ParallelCMSThreads = X

establecer el número de hilos que CMS utilizará cuando se está haciendo las cosas que se pueden hacer en paralelo.

-XX: + CMSParallelRemarkEnabled observación es de serie de forma predeterminada, esto puede acelerar.

-XX: + CMSIncrementalMode permite a la aplicación ejecutarse más por pasuing GC entre fases

-XX: + CMSIncrementalPacing permite JVM a la figura cambio la frecuencia con que se acumula con el tiempo

-XX: CMSIncrementalDutyCycleMin = X Minimm cantidad de tiempo empleado en GC

-XX: CMSIncrementalDutyCycle = X empezar por hacer esto GC% del tiempo

-XX: CMSIncrementalSafetyFactor = X

He encontrado que puede obtener tiempos de pausa generalmente bajos si lo configura de manera que básicamente siempre se esté recopilando. Como la mayor parte del trabajo se realiza en paralelo, terminas con pausas predecibles básicamente regulares.

-XX: CMSFullGCsBeforeCompaction = 1

Éste es muy importante. Le dice al recopilador de CMS que siempre complete la colección antes de que comience una nueva. Sin esto, puede encontrarse con la situación en la que arroja un montón de trabajo y comienza de nuevo.

-XX: + CMSClassUnloadingEnabled

Por defecto, CMS le permitirá a sus PermGen crecen hasta que mata a su aplicación de unas pocas semanas a partir de ahora. Esto detiene eso. Sin embargo, su PermGen solo crecerá si utiliza Reflection, o está haciendo un mal uso de String.intern, o está haciendo algo malo con un cargador de clases, o algunas otras cosas.

La relación de supervivencia y la fijación de la duración del reloj también pueden reproducirse, dependiendo de si tiene objetos de vida larga o corta, y de la cantidad de objetos copiados entre los espacios de sobrevivientes con los que puede vivir. Si sabe que todos sus objetos se van a quedar, puede configurar espacios de supervivencia de tamaño cero, y todo lo que sobreviva a una colección de jóvenes se mantendrá de inmediato.

0

He encontrado utilizando el objeto 'grande' para ir inmediatamente al espacio fijo redujo en gran medida mi joven GC y las fallas de modo concurrente ya que tiende a no tratar de volcar la cantidad de datos +0 superviviente joven (xmn=1536m survivorratio=3 maxTenuringThreashould=5) antes un ciclo completo de CMS puede completarse. Sí, el espacio de mi superviviente es grande, pero una vez cada 2 días aparece algo en la aplicación que lo necesitará (y ejecutamos 12 servidores de aplicaciones cada día para 1 aplicación).

Cuestiones relacionadas