2012-07-04 8 views
8

¿Es posible marcar los objetos java no coleccionables desde la perspectiva de gc para ahorrar en el tiempo de barrido de gc?¿Es posible marcar los objetos java no coleccionables desde la perspectiva de gc para ahorrar en el tiempo de barrido de gc?

Algo a lo largo de las líneas de http://wwwasd.web.cern.ch/wwwasd/lhc++/Objectivity/V5.2/Java/guide/jgdStorage.fm.html y específicamente contenedores que no son de basura allí (no de basura-coleccionables?).

El problema es que tengo un montón de objetos temporales ordinarios, pero tengo incluso más grandes (varios Gigs) de objetos que se almacenan para fines de caché. Sin ninguna razón, el GC de Java atraviesa todos los gigabytes de caché que intentan encontrar algo para recopilar, ya que contienen datos en caché que tienen sus propios tiempos de espera.

De esta manera podría dividir mis datos de manera personalizada en objetos de vida infinita y de vida normal, y con suerte GC sería bastante rápido porque los objetos normales no viven tanto tiempo y equivalen a cantidades menores.

Hay algunas soluciones a este problema, como Apache DirectMemory de comercio y terracota BigMemory (http://terracotta.org/products/bigmemory), sino una solución de Java nativo serían más agradable (me refiero libre y probablemente más fiable ?). También quiero evitar la sobrecarga de serialización, lo que significa que debe ocurrir dentro de la misma JVM. A mi entender DirectMemory y BigMemory operan principalmente fuera del montón lo que significa que los objetos deben ser serializados/deserializados a/desde la memoria fuera de jvm. Simplemente marcar regiones que no sean de gc dentro de jvm parecería una mejor solución. El uso de Archivos para caché tampoco es una opción, tiene la misma sobrecarga de serialización/deserialización inalcanzable. El caso de uso es un servidor HA con muchos datos utilizados en orden aleatorio (humano) y con baja latencia.

+0

¿Qué te hace pensar que BigMemory no es nativo de Java? Parece que lo que realmente quieres decir es ** gratis. ** –

+0

Puedes usar la memoria directa para guardar tus datos en caché (lo cual está desactivado) He hecho esto para mantener 100s de GB fuera de montón. –

+0

@PeterLawrey El uso de memoria directa no es una opción, ya que quiero evitar la sobrecarga de serialización, lo que significa que debe ocurrir dentro del mismo jvm. – Martin

Respuesta

1

¿Es posible marcar los objetos java no coleccionables desde la perspectiva gc para ahorrar en el tiempo de barrido gc?

No, no es posible.

Puede evitar que los objetos sean basura al mantenerlos accesibles, pero el GC aún deberá rastrearlos para verificar la accesibilidad en cada carga; GC (al menos).

Es simplemente mi suposición, que cuando el jvm se muere de hambre comienza a escanear todos esos objetos innecesarios también.

Sí. Eso es correcto. Sin embargo, a menos que tengas MUCHOS objetos que deseas que te traten de esta manera, es probable que la sobrecarga sea insignificante. (Y de todos modos, una mejor idea es darle a la JVM más memoria ... si eso es posible.)

2

Cualquier memoria que administre la JVM también será recolectada por la JVM. Y cualquier objeto "en vivo" que esté directamente disponible para los métodos de Java sin deserialización debe vivir en la memoria JVM. Por lo tanto, a mi entender, no puede haber objetos vivos que sean inmunes a la recolección de basura.

Por otro lado, el uso que describes debe hacer que el enfoque generacional para la recolección de basura sea bastante eficiente. Si sus objetos grandes permanecen por un tiempo, serán revisados ​​para la recuperación con menos frecuencia. Así que dudo que haya mucho que ganar al evitar esos controles.

+0

Es simplemente mi suposición, que cuando el jvm se muere de hambre comienza a escanear todos esos objetos innecesarios también. – Martin

+0

Como regla general, debe suponer que el GC es muy, muy inteligente. –

0

En pocas palabras, para que pueda hacer esto, el algoritmo de recolección de basura debería tener en cuenta una bandera, y tenerlo en cuenta al hacer su trabajo.

No conozco ninguno de los algoritmos estándar de GC que tengan dicho indicador, por lo que para que esto funcione necesitaría escribir su propio algoritmo GC (después de decidir alguna forma factible de comunicarle esta información).

En principio, de hecho, ya ha comenzado por esta pista: está decidiendo cómo se debe hacer la recolección de basura en lugar de estar feliz de dejarla en el GC del JVM. Es la situación que describes un problema mensurable para ti; algo para lo cual la recolección de basura existente es insuficiente, pero su plan funcionaría? Los recolectores de basura están muy bien ajustados, por lo que no me sorprendería que la estrategia predeterminada "ineficiente" sea realmente más rápida que la ingenuamente óptima.

(Hacer la gestión de memoria manual es complicado y propenso a errores en el mejor de los casos;. gestión de algunos memoria a sí mismo mientras se utiliza un colector de basura para manejar el resto parece aún peor espero que había corrido en un montón de casos extremos donde el GC asume que "sabe" lo que está sucediendo con todo el montón, lo que ya no sería cierto. Manténgase alejado si puede ...)

0

Los enfoques recomendados serían el uso de una implementación comercial de RTSJ para evitar el GC, o para usar la memoria del montón. También se podría buscar referencias suaves para los cachés (se recopilan).

No se recomienda: Si por alguna razón no cree que estas opciones sean suficientes, podría buscar en el acceso directo a memoria que es SEGURO (parte de sun.misc.Unsafe). Puede usar el campo 'theUnsafe' para obtener la instancia 'Inseguro'. Inseguro permite asignar/desasignar memoria a través de 'allocateMemory' y 'freeMemory'. Esto no está bajo control de GC ni está limitado por el tamaño de almacenamiento dinámico de JVM. El impacto en GC/aplicación, una vez que se realiza esta ruta, no está garantizado, por lo que el uso de búferes de bytes podría ser el camino a seguir (si no está utilizando una implementación similar a RTSJ).

Espero que esto ayude.

0

Los objetos de Living Java serán siempre forman parte del ciclo de vida de GC. O dicho de otra forma, marcar un objeto para que no sea gc es el mismo orden de sobrecarga que tener una referencia raíz referenciada (por ejemplo, un mapa estático final).

Pero pensando un poco más, es más probable que los datos colocados en un caché sean temporales y eventualmente serán desalojados. En ese momento volverá a comenzar a gustarle la JVM y la GC. Si tiene cientos de GB de datos permanentes, puede reconsiderar la arquitectura de su aplicación y tratar de fragmentar y distribuir sus datos (escalabilidad horizontal).

Por último, se ha trabajado mucho en la serialización, y la sobrecarga de la serialización (no estoy hablando de la mala reputación de ObjectInputStream y ObjectOutputStream) no es tan grande. Más que eso, si sus datos se componen principalmente de tipos primitivos (incluyendo matriz de bytes), existe una forma eficiente de readInt() o readBytes() de de los almacenamientos intermedios de montón (por ejemplo netty.io's ChannelBuffer). Esto podría ser un camino por recorrer.

Cuestiones relacionadas