Bueno, ¡aquí hay varias preguntas en una!
1 - ¿Cómo se gestionan los objetos de corta duración?
Como se indicó anteriormente, la JVM puede tratar perfectamente con una gran cantidad de objetos de corta duración, ya que sigue la Hipótesis Generacional Débil .
Tenga en cuenta que estamos hablando de objetos que llegaron a la memoria principal (montón). Este no es siempre el caso. Muchos de los objetos que crea ni siquiera dejan un registro de CPU. Por ejemplo, considere este for-loop
for(int i=0, i<max, i++) {
// stuff that implies i
}
No pensemos en el desenrollado de bucles (una optimización que la JVM realiza en gran medida en su código). Si max
es igual a Integer.MAX_VALUE
, es posible que el ciclo tarde un poco en ejecutarse. sin embargo, eli
variable nunca escapará del bloque de bucle. Por lo tanto, la JVM pondrá esa variable en un registro de la CPU, la incrementará regularmente pero nunca la enviará de regreso a la memoria principal.
Por lo tanto, crear millones de objetos no es un gran problema si se usan solo localmente. Estarán muertos antes de ser almacenados en el Edén, por lo que la CG ni siquiera los notará.
2 - ¿Es útil reducir la sobrecarga del GC?
Como de costumbre, depende.
Primero, debe habilitar el registro de GC para tener una visión clara de lo que está sucediendo. Puede habilitarlo con -Xloggc:gc.log -XX:+PrintGCDetails
.
Si su aplicación pasa mucho tiempo en un ciclo de GC, entonces sí, ajuste el GC; de lo contrario, es posible que no valga la pena.
Por ejemplo, si tiene un GC joven cada 100 ms que tarda 10 ms, pasa el 10% de su tiempo en el GC y tiene 10 colecciones por segundo (lo que es enorme). En tal caso, no dedicaría tiempo a ajustar el GC, ya que esos 10 GC / s todavía estarían allí.
3 - Algo de experiencia
Tuve un problema similar en una aplicación que estaba creando una gran cantidad de una clase determinada. En los registros de GC, noté que la tasa de creación de la aplicación era de alrededor de 3 GB / s, que es demasiado (vamos ... ¡¿3 gigabytes de datos por segundo?!).
El problema: demasiados GC frecuentes provocados por la creación de demasiados objetos.
En mi caso, adjunté un generador de perfiles de memoria y noté que una clase representaba un gran porcentaje de todos mis objetos. Rastreé las instancias para descubrir que esta clase era básicamente un par de valores booleanos envueltos en un objeto. En ese caso, había dos soluciones disponibles:
Vuelva a trabajar el algoritmo para que no devuelva un par de booleanos, sino que tenga dos métodos que devuelvan cada booleano por separado
Almacene los objetos en caché, sabiendo que solo había 4 instancias diferentes
Elegí el segundo, ya que tuvo el menor impacto en la aplicación y fue fácil de introducir. Me tomó minutos poner una fábrica con un caché no seguro para subprocesos (no necesitaba seguridad para subprocesos, ya que eventualmente tendría solo 4 instancias diferentes).
La tasa de asignación bajó a 1 GB / s, al igual que la frecuencia de GC joven (dividida por 3).
Espero que ayude !