CMS-Recolector de escaneo de marcas simultáneo
Recolector de barrido de marcas concurrente (CMS) (oracle.com)
El recopilador de barrido de marcas concurrente (CMS) está diseñado para aplicaciones que desean reducir los tiempos de pausa de la recolección de basura. Los programas pueden ejecutar aplicaciones. mientras disfruta de los recursos del procesador a través del recolector de basura. Normalmente, las aplicaciones que tienen conjuntos de datos a largo plazo relativamente grandes (un término que genera grandes cantidades) y se ejecutan en máquinas con dos o más procesadores tienden a beneficiarse del uso de dichos recopiladores. Sin embargo, cualquier aplicación que no requiera tiempos de pausa elevados debería considerar el uso de este recopilador. El recopilador de CMS se habilita con la opción de línea de comando -XX:+UseConcMarkSweepGC.
Al igual que los otros recopiladores disponibles, el recopilador CMS es un recopilador intergeneracional, por lo tanto, se realizan colecciones tanto de generaciones jóvenes como de generaciones anteriores; El recolector de CMS intenta reducir el tiempo de pausa causado por la colección principal mediante el uso de un subproceso recolector de basura separado para rastrear los objetos accesibles al mismo tiempo que la ejecución del subproceso de la aplicación. Durante cada ciclo de recopilación importante, el recopilador de CMS pausa brevemente todos los subprocesos de la aplicación al comienzo de la recopilación y nuevamente en la mitad de la misma. La segunda pausa suele ser la más larga de las dos. Durante estas dos pausas, se utilizan varios subprocesos para realizar el trabajo de recopilación. El trabajo de recolección restante, incluida la mayor parte del seguimiento de objetos activos y la limpieza de objetos inalcanzables, lo realizan uno o más subprocesos del recolector de basura que se ejecutan simultáneamente con la aplicación. Las colecciones de la generación más joven se pueden intercalar con las colecciones de la generación anterior en curso y funcionan de manera similar a un recolector de basura paralelo (en particular, los subprocesos de la aplicación se detienen durante las colecciones de la generación más joven).
Fallo del modo concurrente
El recolector de CMS utiliza uno o más subprocesos del recolector de basura que se ejecutan simultáneamente con los subprocesos de la aplicación, con el objetivo de completar la recopilación antes de que expire una generación. Como se mencionó anteriormente, durante el funcionamiento normal, el recopilador de CMS realiza la mayor parte de su trabajo de seguimiento y barrido mientras el subproceso de la aplicación aún se está ejecutando, por lo que el subproceso de la aplicación solo ve pausas breves. Sin embargo, si el recopilador de CMS no puede completar la recopilación de objetos inalcanzables antes de que se llene la generación antigua, o los bloques de espacio libre en la generación antigua no pueden satisfacer la asignación, entonces la aplicación se pausa y se completa con todos los subprocesos de la aplicación detenidos. recolectar. La imposibilidad de completar colecciones al mismo tiempo se denomina falla del modo concurrente e indica la necesidad de ajustar los parámetros del recopilador CMS. Se informa una interrupción del modo concurrente si una recolección concurrente es interrumpida por una recolección de basura explícita (System.gc()) o una recolección de basura requerida para proporcionar información a las herramientas de diagnóstico.
Tiempo de GC excesivo y OutOfMemoryError
Si la recolección de basura demora demasiado, el recolector de CMS arrojará OutOfMemoryError: si la recolección de basura demora más del 98% del tiempo total, y si es menos del Se restaura el 2% del montón y se generará un OutOfMemoryError. Si es necesario, agregue la opción -XX:-UseGCOverheadLimit a la línea de comando para deshabilitar esta función.
Esta política es la misma que en el recopilador paralelo, pero el tiempo dedicado a realizar recopilaciones simultáneas no cuenta para el límite de tiempo del 98 %. En otras palabras, solo las recopilaciones realizadas mientras la aplicación está detenida se contabilizarán como tiempo de GC excesivo. Estas recopilaciones suelen deberse a errores del modo concurrente o solicitudes de recopilación explícitas (por ejemplo, llamadas a System.gc).
Basura flotante
El recolector CMS, como todos los demás recolectores en Java HotSpot VM, es un recolector de seguimiento que al menos identifica todos los objetos accesibles en el montón. En palabras de Richard Jones y Rafael D. Lins en su publicación Garbage Collection: "El recolector CMS es un recolector de seguimiento.
En palabras de Richard Jones y Raphael D. Lins en su publicación Recolección de basura: algoritmos automáticos de memoria dinámica, es un recolector de actualizaciones incrementales. Debido a que los subprocesos de la aplicación y los subprocesos del recolector de basura se ejecutan simultáneamente durante el proceso de recolección principal, los objetos rastreados por la basura. El hilo del recolector puede volverse inalcanzable al final del proceso de recolección. Estos objetos inalcanzables que aún no se han recolectado se denominan basura flotante. La cantidad de basura flotante depende de la duración del ciclo de recolección concurrente y de la frecuencia de las actualizaciones de referencia. conocidas como mutaciones) en la aplicación Además, dado que las generaciones jóvenes y mayores se recolectan de forma independiente, cada generación es equivalente a la otra. Como pauta aproximada, intente aumentar el tamaño de la generación anterior en un 20% para tener en cuenta la basura flotante. Al final de un ciclo de recolección concurrente, la basura flotante se recolectará en el siguiente ciclo de recolección.
Pausa
El recolector de CMS pausa la aplicación dos veces durante un ciclo de recolección concurrente. que llegan directamente desde la raíz (como objetos de la pila de subprocesos de la aplicación y registros, objetos estáticos, etc.) y los objetos de otras partes del montón (como descendientes) se marcan como objetos vivos. final de la fase de seguimiento concurrente y se utiliza para encontrar seguimientos concurrentes que se omiten porque el subproceso de la aplicación actualiza la referencia del objeto después de que el recopilador de CMS completa el seguimiento. La segunda pausa se denomina pausa de comentarios. fase
El seguimiento simultáneo del gráfico de objetos accesibles se produce entre la pausa de marcado inicial y la pausa de remarcado. Durante la fase de seguimiento simultáneo, uno o más subprocesos recolectores de basura simultáneos pueden utilizar recursos del procesador que de otro modo estarían disponibles. por lo tanto, durante esta y otras fases de concurrencia, el rendimiento de la aplicación informática puede disminuir en consecuencia, incluso si el subproceso de la aplicación no está en pausa. La fase de limpieza concurrente recopila objetos que se identifican como inalcanzables una vez que se completa un ciclo de recopilación. El recopilador CMS espera, sin consumir casi recursos informáticos, hasta que comience el siguiente ciclo de recopilación importante.
Inicia un ciclo de recopilación concurrente
En el recopilador en serie, una vez que comienza la generación joven. Se garantiza que la recolección estará llena, la recolección de basura comenzará inmediatamente y todos los subprocesos de la aplicación se detendrán cuando se complete la recolección. Por el contrario, el inicio de la recolección concurrente debe programarse para garantizar que la recolección se complete antes de que la recolección de la generación anterior esté llena; de lo contrario, la aplicación sufrirá problemas de concurrencia. Hay varias formas de iniciar colecciones simultáneas debido a un fallo del modelo.
El recopilador de CMS mantiene una estimación del tiempo restante hasta que se agote la generación anterior y estimaciones de cómo hacerlo. tiempo que tomará un ciclo de recolección concurrente Utilice estas estimaciones dinámicas para iniciar un ciclo de recolección concurrente con el objetivo de completar el ciclo de recolección antes de que se agote la generación antigua. Debido a que la falla en el modo concurrente puede ser muy costosa, estas estimaciones pueden realizar ponderaciones de seguridad.
Si la ocupación de la generación antigua excede la ocupación inicial (porcentaje de la generación antigua), también se iniciará la recolección simultánea. El valor predeterminado para este umbral de ocupación inicial es aproximadamente del 92 %, pero este valor varía de una versión a otra. Este valor se puede ajustar manualmente mediante la opción de línea de comando -XX:CMSInitiatingOccupancyFraction=
Pausas programadas
Las pausas en las colecciones de la generación más joven ocurren independientemente de las de las colecciones de la generación anterior. No se superponen, sino que pueden aparecer en rápida sucesión, de modo que una pausa en una adquisición sigue inmediatamente a una pausa en otra adquisición, apareciendo como una pausa única y más larga. Para evitar esto, los recopiladores de CMS intentarán programar pausas reetiquetadas aproximadamente entre las pausas anteriores y siguientes en la generación más joven. Actualmente, no existe tal disposición para las pausas iniciales de etiquetado, ya que las pausas iniciales de etiquetado suelen ser mucho más cortas que las pausas de reetiquetado.
Modo incremental
Tenga en cuenta que el modo incremental está obsoleto en Java SE 8 y puede eliminarse en una versión importante futura.
El recopilador CMS se puede utilizar en un modo en el que las fases concurrentes se realizan de forma incremental.
Recuerde que durante la fase concurrente, el subproceso del recolector de basura utiliza uno o más procesadores. El propósito del modo incremental es minimizar el impacto de fases concurrentes largas deteniendo periódicamente la fase concurrente y devolviendo el procesador a la aplicación. Este modo, llamado aquí i-cms, divide el trabajo concurrente del recopilador en pequeños períodos de tiempo, programados entre generaciones posteriores de colecciones. Este modo es útil cuando las aplicaciones que requieren los tiempos de pausa bajos proporcionados por el recopilador CMS se ejecutan en máquinas con una pequeña cantidad de procesadores (como 1 o 2).
Un ciclo de cobro concurrente suele incluir los siguientes pasos.
1-Detenga todos los subprocesos de la aplicación, determine el conjunto de objetos accesibles desde el nodo raíz y luego reanude todos los subprocesos de la aplicación.
2-Utilice uno o más procesadores para rastrear simultáneamente el gráfico de objetos accesibles mientras se ejecuta el hilo de la aplicación.
3-Utilice un procesador para rastrear simultáneamente la parte del gráfico de objetos que se ha modificado desde el último rastreo.
4-Detenga todos los subprocesos de la aplicación, retroceda hasta el nodo raíz y partes del gráfico de objetos que pueden haber sido modificados desde la última verificación y luego reanude todos los subprocesos de la aplicación.
5- Utilice también el procesador para barrer los objetos inalcanzables en la lista libre para su asignación.
6- Utilice un procesador para cambiar el tamaño del montón y preparar simultáneamente las estructuras de datos de soporte para el siguiente ciclo de recopilación.
Normalmente, el recopilador CMS utiliza uno o más procesadores durante la fase de marcado concurrente sin renunciar a ellos activamente. Del mismo modo, se utilizan uno o más procesadores durante la fase de limpieza simultánea, pero nuevamente no se abandonan. Esta sobrecarga puede ser demasiado intrusiva para aplicaciones con tiempo de respuesta limitado que, de otro modo, podrían utilizar núcleos de procesamiento, especialmente cuando se ejecutan en sistemas con solo uno o dos procesadores. El patrón incremental resuelve este problema al dividir las fases concurrentes en breves estallidos de actividad, programados entre pequeñas pausas.
El modo i-cms utiliza el ciclo de trabajo para controlar cuánto trabajo puede completar el recopilador de CMS antes de abandonar activamente un procesador. El modo i-cms puede calcular automáticamente el ciclo de trabajo según el comportamiento de la aplicación (método recomendado, ritmo automático) o establecer el ciclo de trabajo en un valor fijo desde la línea de comando.
**Opciones de línea de comando**
Opciones de línea de comando que controlan el modo i-cms. Opciones recomendadas
Opciones recomendadas
Para usar i-cms con Java SE 8, use las siguientes opciones de línea de comando.
-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
Las dos primeras opciones habilitan el recopilador CMS respectivamente y i-cms. Las dos últimas opciones no son necesarias; simplemente escriben información de diagnóstico sobre la recolección de basura en la salida estándar para su posterior visualización y análisis del comportamiento de la recolección de basura.
Para Java SE 5 y versiones anteriores, Oracle recomienda lo siguiente como conjunto inicial de opciones de línea de comando para i-cms.
-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps.
-XX:+CMSIncrementalPacing -XX: CMSIncrementalDutyCycleMin=0
-XX:CMSIncrementalDutyCycle=10
Aunque los valores de las tres opciones que controlan el tamaño de paso automático de i-cms se convierten en valores predeterminados en JavaSE6, es Se recomienda usarlos en JavaSE8 con el mismo valor.
Solución de problemas básicos
La función de ritmo automático de i-cms utiliza estadísticas recopiladas mientras el programa se ejecuta para calcular el ciclo de trabajo, de modo que las recopilaciones simultáneas puedan completarse antes de que se llene el montón.
Sin embargo, el comportamiento pasado no es un predictor perfecto del comportamiento futuro y es posible que las estimaciones no siempre sean lo suficientemente precisas como para evitar que el montón se llene. Si se producen excesivas colecciones completas, pruebe los pasos de la tabla "Solución de problemas de la función de ritmo automático de i-CMS" a continuación, uno a la vez.
Solución de problemas de la función de tamaño de paso automático de i-cms
Resultados de la medición
La siguiente figura muestra el recopilador de CMS usando las opciones -verbose:gc y -XX :+PrintGCDetails salida con algunos detalles adicionales eliminados. Tenga en cuenta que la salida del recopilador CMS se intercala con la salida de otros recopiladores; a menudo se producen muchas recopilaciones auxiliares durante un ciclo de recopilación concurrente.
CMS-initial-mark indica el comienzo del ciclo de recopilación concurrente,
CMS-concurrent-mark indica el final de la fase de marcado concurrente,
CMS -concurrent-sweep Indica el final de la fase de escaneo concurrente.
No se analizó anteriormente la fase de limpieza previa representada por CMS-concurrent-preclean. La limpieza previa representa un trabajo que se puede realizar al mismo tiempo para prepararse para la fase de observación de CMS. La última fase, representada por CMS-concurrent-reset, es prepararse para la próxima recopilación simultánea.
El tiempo de pausa de marcado inicial suele ser corto en relación con el tiempo de pausa de toda la colección de la generación joven. Las pausas para las fases simultáneas (marcado simultáneo, limpieza previa simultánea y purga simultánea) suelen ser mucho más largas que las de la generación más joven, como se muestra en el ejemplo anterior. Sin embargo, tenga en cuenta que la aplicación no se detiene durante estas fases simultáneas. Los tiempos de pausa observados son generalmente comparables a los tiempos de pausa recopilados por la generación más joven. Las pausas de reetiquetado se ven afectadas por ciertas características de la aplicación (por ejemplo, una alta tasa de modificación de objetos aumenta el tiempo de pausa) y también por el tiempo transcurrido desde la última colección de la generación joven (por ejemplo, más objetos en la generación joven aumentan el tiempo de pausa).