Espacio requerido para mantener la matriz de enteros más grande en la memoria

Jan 04 2021

Estoy revisando un algoritmo y mantiene una matriz de números enteros, el tamaño de la entrada es dinámico. Entonces, según mis cálculos, puede tomar tanto como

  integer MAX_VALUE  * int size  = ?   
      2^31 integers  * 4 bytes   = ?
2147483648 integers  * 4 bytes   = 8 Gigabytes

¿Es correcto este cálculo? ¿Usaría la JVM este espacio contiguo para almacenar la matriz int o hay otras cosas que se deben considerar?

Respuestas

3 Eugene Jan 05 2021 at 01:39

El tamaño teórico de la matriz sería:

  • numberOfElementsInTheArray * 4 bytes

  • 12 bytes de encabezados ( int[]es un objeto). En realidad, el tamaño de los encabezados depende de los indicadores que utilizó y de la versión de JVM que esté ejecutando.

  • 4 bytes para mantener el lengthde la matriz

  • relleno.

Por ejemplo: (voy a usar JOL para esto ):

    int [] x = new int[10];
    for(int i=0;i<10;++i){
        x[i] = 9999;
    }
    System.out.println(GraphLayout.parseInstance((Object)x).toPrintable()); 

dará salida:

 [I@7a81197dd object externals:
      ADDRESS       SIZE TYPE PATH                           VALUE
    70fe45268         56 [I                                  [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]

Entonces tiene 56 bytes:

  • 40 para los valores mismos (10 pulgadas * 4 bytes)
  • 12 para encabezados
  • 4 de longitud
  • 0 para relleno

Si cambia esta matriz a Integer, las cosas cambian drásticamente. Integeres un Objeto, por lo que almacenará una referencia dentro de la matriz (que podría ser 4o 8bytes, dependiendo de la UseCompressedOopsbandera), además cada una de las Integerinstancias requerirá 2 encabezados (cada uno Integeres un Objeto).

    Integer[] y = new Integer[10];
    for(int i=0;i<10;++i){
        y[i] = 9999;
    }

    System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());

que mostrará:

   [Ljava.lang.Integer;@369f73a2d footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1        56        56   [Ljava.lang.Integer;
    10        16       160   java.lang.Integer
    11                 216   (total)

Un total de 216 bytes:

  • 4 bytes para cada referencia (lo he UseCompressedOopencendido), 40 bytes en total
  • 12 bytes de encabezados de la matriz
  • 4 bytes de longitud de la matriz
  • Relleno de 0 bytes

Cada referencia de esa matriz apunta a un Integer, cada uno de esos Objetos tendrá 16 bytes:

  • 4 bytes para el interior intque contienen
  • Encabezados de 12 bytes
  • Relleno de 0 bytes
1 BasilBourque Jan 04 2021 at 15:23

Tamaño de matriz máximo < Integer.MAX_VALUE

No, tu máximo es incorrecto.

El límite en la cantidad de elementos en una matriz en Java es un poco menor que Integer.MAX_VALUE(2,147,483,647), dependiendo de la versión de Java, el sistema operativo host y cómo se compiló Java. Vea esta respuesta de Ivan Mamontov sobre la pregunta, ¿Por qué no puedo crear una matriz de gran tamaño? .

Sí, la mayor variedad de int≈ 8 conciertos

Entonces, el tamaño de una matriz máxima intserá aproximadamente de ( Integer.MAX_VALUE - 8L ) * 32Lbits, que es de 68,719,476,448 bits, que es de 8,589,934,556 octetos.

Entonces sí, alrededor de 8 gigas de memoria. Y recuerde: esta es la memoria contigua para una matriz. Entonces:

  • Puede haber un trabajo significativo por parte de la JVM y el sistema operativo host para producir una matriz de este tipo, dependiendo de qué tan fragmentada esté la memoria en ese momento durante el tiempo de ejecución.
  • Si el hardware del host no tiene suficiente memoria real, estará pasando a la memoria virtual donde la paginación resultante puede conducir a un rendimiento terrible.

Siempre haga pruebas del mundo real si realmente está superando estos límites en su trabajo. Y es posible que desee considerar implementaciones alternativas de Java diseñadas para una memoria muy grande, como Zing de Azul Systems.