Nuestros mejores programadores han agotado sus provisiones de café, investigando todo el tiempo por la solución, hasta que Román halló el resultado en Bitbucket y en este momento la comparte aquí.
Solución:
De acuerdo, ha habido mucha discusión y no mucho código 🙂
Aquí hay un punto de referencia rápido. Tiene las advertencias normales cuando se trata de este tipo de cosas: probar la memoria tiene rarezas debido a JITting, etc., pero con números adecuadamente grandes es útil de todos modos. Tiene dos tipos, cada uno con 80 miembros: LotsOfBytes tiene 80 bytes, LotsOfInts tiene 80 enteros. Construimos muchos de ellos, nos aseguramos de que no estén en GC y verificamos el uso de la memoria:
class LotsOfBytes
byte a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
byte b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
byte c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
byte d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
byte e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
class LotsOfInts
int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
public class Test
private static final int SIZE = 1000000;
public static void main(String[] args) throws Exception
LotsOfBytes[] first = new LotsOfBytes[SIZE];
LotsOfInts[] second = new LotsOfInts[SIZE];
System.gc();
long startMem = getMemory();
for (int i=0; i < SIZE; i++)
first[i] = new LotsOfBytes();
System.gc();
long endMem = getMemory();
System.out.println ("Size for LotsOfBytes: " + (endMem-startMem));
System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));
System.gc();
startMem = getMemory();
for (int i=0; i < SIZE; i++)
second[i] = new LotsOfInts();
System.gc();
endMem = getMemory();
System.out.println ("Size for LotsOfInts: " + (endMem-startMem));
System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));
// Make sure nothing gets collected
long total = 0;
for (int i=0; i < SIZE; i++)
total += first[i].a0 + second[i].a0;
System.out.println(total);
private static long getMemory()
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
Salida en mi caja:
Size for LotsOfBytes: 88811688
Average size: 88.811688
Size for LotsOfInts: 327076360
Average size: 327.07636
0
Entonces, obviamente, hay algo de sobrecarga: 8 bytes por lo que parece, aunque de alguna manera solo 7 para LotsOfInts (? Como dije, hay rarezas aquí), pero el punto es que los campos de bytes parecen estar empaquetados para LotsOfBytes de tal manera que toma (después de la eliminación de la sobrecarga) solo una cuarta parte de la memoria que LotsOfInts.
Sí, una variable de byte en Java tiene, de hecho, 4 bytes en la memoria. Sin embargo, esto no se sostiene true para matrices. El almacenamiento de un byte array de 20 bytes es de hecho sólo 20 bytes en la memoria.
Esto se debe a que Java Bytecode Language solo conoce dos tipos de números enteros: ints y longs. Por lo tanto, debe manejar todos los números internamente como cualquier tipo y estos tipos tienen 4 y 8 bytes en la memoria.
Sin embargo, Java conoce matrices con todos los formatos de números enteros. Entonces, el almacenamiento de matrices cortas es, de hecho, dos bytes por entrada y un byte por entrada para matrices de bytes.
La razón por la que sigo diciendo "el almacenamiento de" es que un array también es un objeto en Java y cada objeto requiere varios bytes de almacenamiento por sí mismo, independientemente del almacenamiento que las variables de instancia o el array almacenamiento en caso de requerir arreglos.
Java nunca es específico de una implementación o plataforma (al menos en lo que respecta a los tamaños de tipos primitivos). Siempre se garantiza que los tipos primitivos permanecerán iguales sin importar en qué plataforma se encuentre. Esto difiere (y se consideró una mejora) de C y C++, donde algunos de los tipos primitivos eran específicos de la plataforma.
Dado que es más rápido para el sistema operativo subyacente abordar cuatro (u ocho, en un sistema de 64 bits) bytes a la vez, la JVM puede asignar más bytes para almacenar un byte primitivo, pero solo puede almacenar valores de -128 a 127 en él.
Puedes añadir valor a nuestra información cooperando tu veteranía en las notas.