Diferencia entre "en el montón" y "fuera del montón"


Respuestas:


169

El almacén en el montón se refiere a los objetos que estarán presentes en el montón de Java (y también sujetos a GC). Por otro lado, el almacén fuera del montón se refiere a objetos (serializados) que son administrados por EHCache, pero almacenados fuera del montón (y que tampoco están sujetos a GC). A medida que el almacén fuera del montón continúa siendo administrado en la memoria, es un poco más lento que el almacén en el montón, pero aún más rápido que el almacén del disco.

Los detalles internos involucrados en la administración y el uso de la tienda fuera del montón no son muy evidentes en el enlace publicado en la pregunta, por lo que sería aconsejable revisar los detalles de Terracotta BigMemory , que se utiliza para administrar el disco. Tienda. BigMemory (la tienda fuera del montón) se debe utilizar para evitar la sobrecarga de GC en un montón de varios Megabytes o Gigabytes de gran tamaño. BigMemory utiliza el espacio de direcciones de memoria del proceso JVM, a través de ByteBuffers directos que no están sujetos a GC a diferencia de otros objetos Java nativos.


18
+1 por mencionar ByteBuffers directos para una mayor exploración;)
Max

3
Los ByteBuffers directos ofrecen acceso a la memoria no administrada, pero están sujetos a GC (a diferencia de los datos a los que apuntan). Esto es importante porque el GC recopilará un ByteBuffer directo (el tipo ByteBuffer.allocateDirect, no el tipo MMap) y, cuando se recoja, se desencadenará Deallocater, que también recogerá efectivamente la memoria no administrada.
Nitsan Wakart

El uso de inseguro para asignar objetos parece tener un rendimiento significativamente mejor de lectura y escritura sobre Onheap / DirectByteBuffers / ByteBuffers. ashkrit.blogspot.com/2013/07/…
Joe C

98

de http://code.google.com/p/fast-serialization/wiki/QuickStartHeapOff

¿Qué es la descarga de almacenamiento dinámico?

Por lo general, todos los objetos no temporales que asigna son administrados por el recolector de basura de java. Aunque la VM hace un trabajo decente haciendo la recolección de basura, en cierto punto la VM tiene que hacer un llamado 'GC completo'. Un GC completo implica escanear el montón asignado completo, lo que significa que las pausas / ralentizaciones del GC son proporcionales al tamaño del montón de una aplicación. Así que no confíes en ninguna persona que te diga 'La memoria es barata'. En Java, el consumo de memoria perjudica el rendimiento. Además, puede obtener pausas notables utilizando tamaños de almacenamiento dinámico> 1 Gb. Esto puede ser desagradable si tiene algo que hacer casi en tiempo real, en un clúster o en una cuadrícula, un proceso de Java puede dejar de responder y caerse del clúster.

Sin embargo, las aplicaciones de servidor de hoy en día (creadas con frecuencia sobre marcos hinchados ;-)) requieren montones que superan los 4 Gb.

Una solución a estos requisitos de memoria es 'descargar' partes de los objetos al montón no Java (asignado directamente desde el sistema operativo). Afortunadamente, java.nio proporciona clases para asignar / leer y escribir directamente fragmentos de memoria 'no administrados' (incluso archivos mapeados en memoria).

Entonces uno puede asignar grandes cantidades de memoria 'no administrada' y usar esto para guardar objetos allí. Para guardar objetos arbitrarios en la memoria no administrada, la solución más viable es el uso de la serialización. Esto significa que la aplicación serializa objetos en la memoria offheap, luego el objeto puede leerse usando la deserialización.

El tamaño de almacenamiento dinámico administrado por la máquina virtual Java puede mantenerse pequeño, por lo que las pausas de GC están en el milis, todos están contentos, trabajo hecho.

Está claro que el rendimiento de dicho búfer fuera del montón depende principalmente del rendimiento de la implementación de la serialización. Buenas noticias: por alguna razón, la serialización FST es bastante rápida :-).

Ejemplos de escenarios de uso:

  • Caché de sesión en una aplicación de servidor. Use un archivo mapeado de memoria para almacenar gigabytes de sesiones de usuario (inactivas). Una vez que el usuario inicia sesión en su aplicación, puede acceder rápidamente a los datos relacionados con el usuario sin tener que lidiar con una base de datos.
  • Almacenamiento en caché de resultados computacionales (consultas, páginas html, ...) (solo aplicable si el cálculo es más lento que la deserialización del objeto de resultado de c).
  • Persistencia muy simple y rápida utilizando archivos mapeados en memoria

Editar: para algunos escenarios, uno podría elegir algoritmos de recolección de basura más sofisticados como ConcurrentMarkAndSweep o G1 para admitir montones más grandes (pero esto también tiene sus límites más allá de los montones de 16 GB). También hay una JVM comercial con GC 'Azul sin pausa' mejorado disponible.


44
"asigna grandes cantidades de memoria 'no administrada' y úsala para guardar objetos allí": no puedes guardar objetos fuera del montón. Puede almacenar primitivas, puede envolverlas en la biblioteca que desee, pero estos no son Objetos. Los datos que coloca fuera del montón no tienen encabezado de objeto, no puede sincronizarlo, no puede hacer referencia a él con un campo de referencia en algún otro objeto.
Nitsan Wakart

41

El montón es el lugar en la memoria donde viven los objetos asignados dinámicamente. Si lo usaste, newentonces está en el montón. Eso es opuesto al espacio de pila, que es donde vive la pila de funciones. Si tiene una variable local, entonces esa referencia está en la pila. El montón de Java está sujeto a la recolección de basura y los objetos se pueden usar directamente.

El almacenamiento fuera del montón de EHCache saca su objeto normal del montón, lo serializa y lo almacena como bytes en una porción de memoria que EHCache administra. Es como almacenarlo en el disco pero todavía está en la RAM. Los objetos no son directamente utilizables en este estado, primero deben ser deserializados. Tampoco está sujeto a recolección de basura.


¿No es simplemente todavía en el montón sino como una forma serializada?
Pacerier

1
¿Cómo lo hace más eficiente?
Pacerier

2
Hay muchas formas Dado que los objetos ya no están en el montón principal de Java, no pierden el tiempo del recolector de basura, no fragmentan el montón de JVM y liberan espacio para otros objetos más utilizados. Además, dado que están serializados y probablemente no sean necesarios en el futuro inmediato, se pueden comprimir, mover según sea necesario o incluso paginar en el disco.
Adam

1
En Hotspot, el tiempo de pausa del GC depende directamente del tamaño del montón. BigMemory proporciona esta compensación al utilizar RAM en lugar de almacenamiento dinámico, para mantener la pausa del GC al mínimo y evitar el costo IO del acceso al disco.
Chander Shivdasani


1

La JVM no sabe nada acerca de la memoria fuera del montón. Ehcache implementa una memoria caché en disco, así como una memoria caché en memoria.


1

No 100%; sin embargo, parece que el montón es un objeto o un conjunto de espacio asignado (en RAM) que está integrado en la funcionalidad del código, ya sea Java o una funcionalidad más probable del propio ehcache, y el Ram fuera del montón es su propio sistema como bien; sin embargo, parece que esto es una magnitud más lenta ya que no está tan organizado, lo que significa que puede no usar un montón (es decir, un conjunto largo de espacio de ram), y en su lugar usa diferentes espacios de direcciones que probablemente lo hagan un poco menos eficiente.

Entonces, por supuesto, el siguiente nivel más bajo es el espacio en el disco duro.

No uso ehcache, por lo que es posible que no desee confiar en mí, pero eso es lo que obtuve de su documentación.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.