Espace requis pour conserver le plus grand tableau d'entiers en mémoire

Jan 04 2021

Je suis en train de passer en revue un algorithme et il conserve un tableau d'entiers, la taille de l'entrée est dynamique. Donc, selon mes calculs, cela peut prendre autant que

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

Ce calcul est-il correct? la JVM utiliserait-elle cet espace très contigu pour stocker le tableau int ou y a-t-il d'autres choses à prendre en compte?

Réponses

3 Eugene Jan 05 2021 at 01:39

La taille théorique du tableau serait:

  • numberOfElementsInTheArray * 4 octets

  • 12 octets d'en-têtes ( int[]est un objet). En fait, la taille des en-têtes dépend des indicateurs que vous avez utilisés et de la version JVM que vous exécutez

  • 4 octets pour garder le lengthdu tableau

  • rembourrage.

Par exemple: (je vais utiliser JOL pour cela ):

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

affichera:

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

Donc, il a 56 bytes:

  • 40 pour les valeurs elles-mêmes (10 pouces * 4 octets)
  • 12 pour les en-têtes
  • 4 pour la longueur
  • 0 pour le rembourrage

Si vous modifiez ce tableau en Integer, les choses changent radicalement. Integerest un objet, vous allez donc stocker une référence à l'intérieur du tableau (qui pourrait être 4ou 8octets, selon l' UseCompressedOopsindicateur), plus chacune des Integerinstances nécessitera 2 en-têtes (chacun Integerest un objet).

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

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

qui montrera:

   [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 octets pour chaque référence (j'ai UseCompressedOopactivé), 40 octets au total
  • 12 octets en-têtes du tableau
  • 4 octets de longueur du tableau
  • 0 octets de remplissage

Chaque référence de ce tableau pointe vers un Integer, chacun de ces objets aura 16 bytes:

  • 4 octets pour l'intérieur intqu'ils détiennent
  • En-têtes de 12 octets
  • 0 octets de remplissage
1 BasilBourque Jan 04 2021 at 15:23

Taille maximale du tableau < Integer.MAX_VALUE

Non, votre maximum est incorrect.

La limite du nombre d'éléments dans un tableau en Java est un peu inférieure à Integer.MAX_VALUE(2 147 483 647), selon la version de Java, le système d'exploitation hôte et la manière dont Java a été compilé. Voir cette réponse d'Ivan Mamontov sur la question, pourquoi je ne peux pas créer un tableau de grande taille? .

Oui, le plus grand choix de int8 concerts

Ainsi, la taille d'un tableau maximal de intsera approximativement de ( Integer.MAX_VALUE - 8L ) * 32Lbits, soit 68 719 476 448 bits, soit 8 589 934 556 octets.

Alors oui, environ 8 Go de mémoire. Et rappelez-vous: il s'agit de la mémoire contiguë pour un tableau. Donc:

  • Il peut y avoir un travail important de la part de la JVM et du système d'exploitation hôte pour produire un tel tableau en fonction de la fragmentation de la mémoire à ce moment pendant l'exécution.
  • Si le matériel hôte ne dispose pas de suffisamment de mémoire réelle, vous vous retrouverez dans la mémoire virtuelle où la pagination qui en résulte peut entraîner des performances terribles.

Faites toujours des tests dans le monde réel si vous repoussez vraiment ces limites dans votre travail. Et vous voudrez peut-être envisager des implémentations alternatives de Java conçues pour une très grande mémoire, telles que Zing by Azul Systems.