viernes, 13 de marzo de 2009

Compressed pointers. Compressed oops.

Una de mis optimizaciones favoritas que aparecerán en la update 14 de Java 6 (actualmente en build 1, como os indiqué en un artículo anterior), y que ya estaba disponible en las "performance releases" es la compresión de punteros en la máquina virtual de 64 bits.

En Sun le llaman "compressed oops".

El concepto es sencillo, y en realidad desde hace muuuuuucho lo tiene implementado JRockit, si los objetos mapeados es inferior de 4.000 millones de objetos (unos 32 gigas de RAM), se activa esta optimización, que reduciéndolo mucho puede explicarse de la siguiente manera: no es necesario que los punteros sean de 64 bits, pueden ser de de 32 bits, y hacer la resta con el punto de inicio de la memoria del S.O. utilizada. Esto es una reducción, en realidad es más complejo claro... Según el enlace que pongo abajo, literalmente: "Compressed oops represent managed pointers (in many but not all places in the JVM) as 32-bit values which must be scaled by a factor of 8 and added to a 64-bit base address to find the object they refer to. This allows applications to address up to four billion objects (not bytes), or a heap size of up to about 32Gb. At the same time, data structure compactness is competitive with ILP32 mode."

Esto puede consiguir una mejora general del rendimiento de aproximadamente un 3%: Por un lado se consigue que todas las estructuras internas ocupen menos memoria (los punteros ocupan la mitad, y en algunos informes se habla de un consumo de hasta 1,5 veces mayor porque aquí hay mucho puntero aunque lo primero que nos dicen cuando aprendemos Java es que aquí no hay ni un solo puntero) y por otro lado se incrementa la capacidad de las cachés del servidor y of course por los buses puede trasitar el doble de información (en lo que a punteros se refiere) en el mismo tiempo.

Obivamente el mapeo siempre hay que hacerlo y supone una penalización, pero la ganancia por el otro lado lo compensa con creces. Es decir, la máquina virtual de 64 bits será "casi" tan competitiva como la de 32 bits, no llegará a ser lo mismo pero la diferencia será inapreciable...

Aunque algunos piensan que esta optimización sólo funciona si el heap máximo es inferior o igual a 4 GBytes (por aquello de los 32 bits), no es cierto. Como digo arriba son 2^32 objetos referenciados por los punteros. Claro, si cada punterio apuntara a una estructura de 1 byte, esto sería 2 gigas, pero según las medias estadísticas de tamaño de objetos en heap, en la práctica supone aproximadamente 32 gigas efectivos teniendo en cuenta que esta optimización sólo afecta al código compilado no al interpretado, y en función del caso de uso esto es mucho mayor... vamos que la optimización afecta al 99% de los sistemas del mundo mundial.

¿Te suena la frase de que las máquinas virtuales de 64 bits son más lentas o que consumen más memoria? Bien, pues ya no será una afirmación válida...

Más información sobre compresión de punteros, el primer enlace es el clarificador:

No hay comentarios: