7
votes

Combien d'espace un tableau occupe-t-il?

Si je crée 10 entiers et un tableau entier de 10, y aura-t-il une différence dans l'espace total occupé?

Je dois créer une gamme booléenne de millions d'enregistrements. Je tiens donc à comprendre combien d'espace sera pris par la matrice elle-même.


4 commentaires

Oui, un tableau est un objet, il a donc plus que les valeurs. Le tableau prendra plus d'espace.


Pourrait être, mais cela vaut-il la peine de penser à cela?


Regardez ce Java.dzone.com/articles/java-how-much -Memory-do


Eh bien, je veux savoir si je crée une gamme booléenne de millions d'enregistrements, combien d'espace sera pris par un tableau


9 Réponses :


0
votes

En termes d'espace RAM, il n'y a pas de différence réelle


2 commentaires

Mauvaise réponse. Vérifiez les commentaires et les autres réponses.


+1 Il y a une différence relative élevée, mais à moins que vous ne le faites beaucoup cela ne fera aucune différence réelle à votre application.



2
votes

en Java, vous avez à la fois entier et INT. Supposant que vous parlez de INT, un éventail d'INTS est considéré comme un objet et des objets ont des métadonnées afin qu'un tableau de 10 INT occupe plus de 10 variables INT


0 commentaires

4
votes

Des calculs de limites inférieures brutes:

Chaque int prend quatre octets. = 40 octets pour dix

Un réseau INT prend en charge quatre octets pour chaque composant plus quatre octets pour stocker la longueur et encore quatre octets pour stocker la référence. = 48 octets (+ peut-être un peu de rembourrage pour aligner tous les objets à 8 limites d'octets)

Un entier occupe au moins 8 octets, ainsi que les quatre autres octets pour stocker la référence. = au moins 120 pour dix

Un réseau entier occupe au moins 120 octets pour les dix entiers plus quatre octets pour la longueur, puis peut-être un peu de rembourrage pour l'alignement. Plus quatre octets pour stocker la référence à elle. (@Marko indique qu'il a même mesuré environ 28 octets par emplacement, de sorte que 280 octets pour un tableau de dix).


2 commentaires

Sur 64 bits Java, tous les pointeurs prennent huit octets au lieu de quatre, faisant la différence entre primitif et wrapper encore plus grand.


J'ai mesuré, un entier [] plein d'instances entières occupe 28 octets par emplacement en moyenne (JVM 64 bits). Un fait amusant est que c'est exactement la même chose qu'une matrice d'objet s.



6
votes

Un tableau d'entiers est représenté comme un bloc de mémoire pour maintenir les entiers et un en-tête d'objet. L'en-tête d'objet prend généralement 3 mots 32 bits pour un JVM 32 bits, mais c'est dépendant de la plate-forme. (L'en-tête contient des bits d'indicateur, une référence à un descripteur de classe, d'espace pour les informations de verrouillage primitif et la longueur de la matrice réelle. Plus le rembourrage.)

Un tableau de 10 INTS prend probablement probablement dans la région de 13 * 4 octets.

Dans l'affaire sur un entier [] , chaque objet entier a une en-tête de 2 mots et un champ de mots contenant la valeur réelle. Et vous devez également ajouter un remplissage et 1 mot (ou 1 à 2 mots sur un JVM 64 bits) pour la référence. C'est typiquement 5 mots ou 20 octets par élément de la matrice ... à moins que certains objets entier n'apparaissent dans plusieurs endroits de la matrice.


Notes:

  1. Le nombre de mots réellement utilisés pour une référence sur un JVM 64 bits dépend de la question de savoir si "OOPS comprimé" sont utilisés.
  2. sur certains JVM, les nœuds de tas sont alloués en multiples de 16 octets ... qui gonflent l'utilisation de l'espace (par exemple le rembourrage mentionné ci-dessus).
  3. Si vous prenez l'identité Hashcode d'un objet et survit à la prochaine collection de déchets, sa taille est gonflée par au moins 4 octets pour mettre en cache la valeur de code HASHCODE.
  4. Ces numéros sont toutes des versions et des fournisseurs spécifiques, en plus des sources de variabilité énumérées ci-dessus.

4 commentaires

De plus, vous avez besoin de quatre (ou huit sur 64 bits JVM) pour chacun des pointeurs de ces objets.


@Thilo en fait, il n'est pas facile de prédire la taille du pointeur. En raison de l'alignement, la JVM peut toujours s'en sortir avec des pointeurs de 4 octets. C'est ce que j'observe à mon système.


@Markotopolnik: C'est génial! Je m'inquiétais à ce sujet un peu de retour, et quand j'ai vérifié, les réponses que j'ai eues étaient que les pointeurs ont besoin de 8 octets, à moins que vous ne activiez une option de compression supplémentaire. Stackoverflow.com/questions/3733215/... Heureux de voir que c'est corrigé maintenant (il semblait un peu excessif).


@ Thil0 - J'ai déjà inclus ça ... "et un mot pour la référence" .



0
votes

Si vous utilisez un tableau, vous avez 11 objets, 10 entiers et la matrice, plus des tableaux ont d'autres métadonnées à l'intérieur. Donc, l'utilisation d'un tableau prendra plus d'espace mémoire.

maintenant pour de vrai. Ce type de question se présente en réalité dans des entretiens et des examens d'embauche, et qui vous montre quel type d'intervieweur ou d'enseignant vous avez ... avec tant de couches d'abstraction travaillant là-bas dans la machine virtuelle et dans le système d'exploitation même, quel est le point En pensant à ce sujet? Micro-optimisant la mémoire ...!


1 commentaires

Il ne pouvait être que 1 objet s'il s'agit d'une primitive int [] (la question est un peu floue à ce point)



2
votes

À la lumière de votre commentaire, il ne fera pas beaucoup de différence si vous avez utilisé un tableau. Le tableau utilisera une quantité négligeable de mémoire pour sa fonctionnalité elle-même. Tout autre mémoire sera utilisé par les objets stockés.

Edit: Ce que vous devez comprendre, c'est que la différence entre le wrapper booléen et le type primitif booléen. Les types d'emballage prendront généralement plus d'espace que les primitives. Donc, pour des missions d'enregistrements, essayez d'aller avec les primitives.

Une autre chose à garder à l'esprit lors de la réalisation de missions d'enregistrement comme vous l'avez dit est Java AutoBoxing. Le coup de performance peut être important si vous l'utilisez involontairement dans une fonction qui traverse l'ensemble du tableau.


4 commentaires

La différence peut être assez grande, si elle est entier [] vs int [] . Dans ce cas, les objets d'emballage prendraient la majeure partie de l'espace.


D'accord. Réponse modifiée. Mais la sémantique des array prendra la même mémoire que je pense. La principale différence provient des objets / éléments stockés dans le tableau. Donc, je ne pense pas que j'étais ça hors de la marque.


L'argument de type wrapper est bon, mais pas tellement pour Boolean , car il n'y a que deux valeurs possibles, il y aura donc beaucoup de partage du pointeur. Bien sûr, vous devez toujours stocker quatre (ou huit) octets pour la référence, au lieu de "juste" pour le bool.


Oui pas tellement mais assez encore pour faire une différence d'énorme nombre d'enregistrements.



1
votes

Ce que vous pouvez faire est mesure : xxx

Bien sûr, cela va avec la norme de non-responsabilité: gc () n'a pas de Des garanties particulières, donc répéter plusieurs fois pour voir si vous obtenez des résultats cohérents. Sur ma machine, la réponse est un octeen par booléen .


4 commentaires

Si je voulais mesurer, j'utiliserais Jmap et regarderais le dépotoir de la mémoire en tas.


@Thilo Si vous aviez un système déjà en cours d'exécution, ce serait votre meilleure option, mais dans ce cas, il s'agit d'un travail supplémentaire en train de creuser par la décharge.


@Thilo j'ai déjà beaucoup d'expérience avec cette méthode et la précision est géniale.


@Thilo pour l'exhaustivité, je viens de vérifier la Dump AppProche. Il a signalé une occupation de 64 Mo lors de l'ajout de la taille de l'allocation rapportée, mais 56 Mo de tas total est pris. Le diff est qu'il a signalé 8 octets / emplacement dans une matrice d'objet, où il s'agit en fait de 4 octets / emplacement. Je m'envoie définitivement avec mon approche :-)



0
votes

Je veux dire si je crée 10 entiers et une éventail entier de 10, y aura-t-il toute différence dans l'espace total occupé. P>

int[] nums = new int[10];

0 commentaires

1
votes

Il n'est pas nécessaire de ne pas refléter mal sur l'enseignant / intervieweur.

Combien vous souciez de la taille et de l'alignement des variables en mémoire dépend de la performance de votre code. Il compte beaucoup si votre logiciel traite des transactions (EFT / BOTE Market), par exemple.

La taille, l'alignement et l'emballage de vos variables en mémoire peuvent influencer les hits / miss caches de la CPU, ce qui peut influer sur la performance de votre code jusqu'à un facteur de 100.

Ce n'est pas une mauvaise chose de savoir ce qui se passe à un niveau bas, tant que vous utilisez de la performance de manière responsable de la performance.

Par exemple, je suis venu à ce fil parce que je devais connaître la réponse à cette question, de sorte que je puisse former mes matrices de primitives pour remplir un multiple entier de lignes de cache de la CPU, car j'ai besoin du code qui effectue des calculs. sur ces matrices de primitives pour exécuter rapidement parce que j'ai une fenêtre finie dans laquelle j'ai besoin de mes calculs pour être prêts pour le consommateur du résultat.


0 commentaires