2009-07-24 26 views
8

Leí en algún lugar que Java puede asignar memoria para objetos en aproximadamente 12 instrucciones de la máquina. Es bastante impresionante para mí. Por lo que yo entiendo, uno de los trucos que usa JVM es la asignación previa de memoria en fragmentos. Esta ayuda para minimizar el número de solicitudes al sistema operativo, que es bastante caro, supongo. Pero incluso las operaciones CAS pueden costar hasta 150 ciclos en procesadores modernos.Asignación de memoria sin bloqueo de Java

Entonces, ¿podría alguien explicar el costo real de la asignación de memoria en Java y qué trucos utiliza JVM para acelerar la asignación?

+0

Una JVM típica sólo utilizará el sistema operativo para añadir más memoria a la pila. La mayoría de las veces está reutilizando lo que ya tiene. –

Respuesta

17

La JVM pre-asigna un área de memoria para cada hilo (TLA o hilo de área local). Cuando un hilo necesita asignar memoria, usará "Ajustar la asignación del puntero" dentro de esa área. (Si el "puntero libre" apunta a la dirección 10, y el objeto a asignar es el tamaño 50, entonces simplemente colocamos el puntero libre a 60, y le decimos al hilo que puede usar la memoria entre 10 y 59 para el objeto) .

+0

Muchas gracias. Es algo que he estado buscando, pero no sabía cómo preguntarle a Google al respecto. :) Pero es interesante ... La única mención que he encontrado sobre TLA es en Oracle JRock JVM (flag -XXtlaSize). ¿Esta característica está presente en Sun JVM? –

+1

La terminología de Sun es Thread Local Allocation Buffer. Los estándares TLA para el búfer Look-Aside de traducción (culpan a IBM) y se refieren a los mapas de caché de hardware. –

+1

Tienes razón, he encontrado información. Gracias. Btw, supongo que la traducción Lookaside Buffer se abrevia como TLB :) http://en.wikipedia.org/wiki/Translation_lookaside_buffer –

2

El mejor truco es el basurero generacional. Esto mantiene el montón sin fragmentar, por lo que asignar memoria aumenta el puntero al espacio libre y devuelve el valor anterior. Si se agota la memoria, la copia de recolección de basura se opone y crea así un nuevo montón no fragmentado.

Como diferentes hilos tienen que sincronizarse sobre el puntero a la memoria libre, si lo aumentan, preasignan trozos. Entonces, un hilo puede asignar nueva memoria, sin el bloqueo.

Todo esto se explica con más detalle aquí: http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

1

No hay un único asignador de memoria para la JVM. IIRC correctamente la JVM de Sun y la memoria administrada de IBM de manera diferente. Sin embargo, en general, la forma en que funcionará la JVM es que inicialmente asignará una pieza de memoria, este segmento será lo suficientemente pequeño como para vivir en la memoria caché de los procesadores, lo que hace que todo el acceso sea extremadamente rápido.

Como dentro de la aplicación crea objetos, los objetos tomarán memoria desde dentro de este segmento. La asignación de objetos dentro del segmento es simplemente aritmética del puntero.

Inicialmente, la dirección de desplazamiento en el segmento recién acuñado será cero. El primer objeto asignado tendrá una 'dirección' (en realidad una compensación en el segmento) de cero. Cuando asigna un objeto, el administrador de memoria sabrá cuán grande es el objeto, asignará ese espacio dentro del segmento (16 bytes dicen) y luego incrementará su "dirección de desplazamiento" en esa cantidad, lo que significa que la asignación de memoria es deslumbrante, solo puntero aritmética.

Sun tienen un libro blanco aquí http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf e IBM solía tener un montón de cosas en ibm.com/developerworks