web-dev-qa-db-fra.com

Un simple "Hello World" a besoin d'une mémoire virtuelle 10G sur une machine 64 bits contre 1G à 32 bits?

En exécutant un simple programme Java sur notre machine de production, j'ai remarqué que ce programme mange plus de virtus 10G. Je sais que la mémoire virtuelle n'est pas si pertinente, mais au moins je voudrais comprendre pourquoi cela est nécessaire.

public class Main {
  public static void main(String[] args) {
        System.out.println("Hello World!");
        try {
                Thread.sleep(10000);
        } catch(InterruptedException e) {
                /* ignored */
        }
  }
}

Voici ce que top dit quand j'exécute ce petit programme:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
18764 myuser    20   0 10.2g  20m 8128 S  1.7  0.1   0:00.05 Java

Est-ce que quelqu'un sait pourquoi cela se produit?

uname -a dit:

Linux m4fxhpsrm1dg 2.6.32-358.18.1.el6.x86_64 #1 SMP Fri Aug 2 17:04:38 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux

Sur une ancienne machine 32 bits Linux, le même programme ne consomme qu'environ 1G virt. L'ancienne machine a 4 Go de RAM, la nouvelle 32 Go.

66
user3246431

Les tailles par défaut pour le tas initial et le tas maximum sont définis comme un pourcentage de la mémoire physique de la machine, dont un serveur de production a de nos jours tendance à avoir beaucoup .

Vous pouvez choisir les deux via les options de ligne de commande - Xms et -Xmx .

86
Michael Borgwardt

La mémoire virtuelle n'a pas vraiment d'importance pour vous.

La différence fondamentale entre 32 bits et 64 bits est que l'espace d'adressage en 64 bits est incroyablement grand. Si 10 GiB vous ressemble beaucoup, notez que .NET sur 64 bits peut utiliser des TiB de mémoire comme ceci. Pourtant sur 32 bits, .NET est beaucoup plus conservateur (et ainsi est JVM) - l'espace d'adressage est de 4 GiB total - ce n'est pas beaucoup.

Mais ce n'est pas pertinent - cela n'a pas d'importance. C'est juste une chose qui simplifie considérablement la programmation et n'a aucun effet négatif sur le système d'exploitation hôte. Il crée un espace d'adressage continu pour le VM à utiliser, ce qui signifie que vous n'avez pas à fragmenter le tas (ou pire, la pile, où il est plus ou moins impossible - mais ceux-ci ont tendance à être seulement un MiB ou plus) car vous avez besoin de plus de mémoire "réelle". Lorsque vous validez enfin la mémoire virtuelle, elle devient légèrement plus réelle - à ce stade, elle doit plus ou moins être soutenue par certains stockage de données - que ce soit le fichier de page (swap) ou la RAM physique.

Le fait est que l'emplacement physique de la mémoire n'est pas nécessairement continu, mais cela se fait hors de votre portée, et la cartographie est généralement très rapide. D'un autre côté, devoir, par exemple, indexer un tableau, qui est en fait fragmenté sur 10 blocs de mémoire d'adresse virtuelle différents, c'est (complètement inutile) de travail.

Donc, vous l'avez - la mémoire virtuelle est presque gratuite sur 64 bits. L'approche de base est "si elle est là, utilisez-la". Vous ne limitez pas les autres applications, et cela vous fait économiser un peu de travail si vous le faites finissez par l'utiliser. Mais jusqu'à ce moment, vous n'avez qu'une réservation. Cela ne se traduit pas du tout en mémoire physique. Vous ne payez pas pour les amis qui pourraient venir ce soir et s'asseoir à votre table, mais vous avez toujours de la place pour qu'ils s'assoient s'ils viennent - et ce n'est que lorsqu'ils arrivent enfin que vous êtes réellement "facturé".

Consultez cette question pour plus d'informations sur la manière dont Java se comporte sur différentes machines et avec différentes versions: Quelle est la taille de segment maximale par défaut pour la machine virtuelle Java de Sun à partir de Java SE 6? La taille maximale du segment détermine également la quantité de mémoire virtuelle réservée, car le segment doit être un espace d'adressage continu. S'il n'était pas pré-réservé, il se peut que le segment ne puisse pas étendre à cette valeur maximale, car quelqu'un d'autre a réservé une région d'espace d'adressage à l'endroit où le tas doit être développé.

46
Luaan

Ce n'est pas votre programme qui utilise cette mémoire, c'est le Java VM réservant cette mémoire, quel que soit le programme chargé).

7
Pieter B

Il s'avère que sur une architecture informatique moderne qui utilise l'adressage de la mémoire virtuelle (où "l'espace mémoire" qu'une application voit ne se rapporte pas réellement à la mémoire qui est en fait physiquement allouée), la façon dont une grande partie de cet "espace mémoire" virtuel est donnée à une application au démarrage. Cela ne signifie pas que cette quantité de mémoire a été allouée par le système.

Si une application voit un espace d'adressage virtuel de 10 Go, tout ce qu'elle signale à l'application est qu'elle peut utiliser des adresses mémoire jusqu'à 10 Go si elle le souhaite. Cependant, la mémoire n'est pas réellement allouée en physique RAM jusqu'à ce qu'elle soit réellement écrite, et cela se fait page par page, où une page est une section de mémoire de 4 Ko. La l'espace d'adressage virtuel, c'est juste cela - complètement virtuel jusqu'à ce qu'il soit réellement utilisé.

Supposons qu'une application dispose de 10 Go d'espace d'adressage et qu'elle commence à en utiliser une partie. Lorsqu'une page "fraîche" - précédemment intacte - de cette mémoire virtuelle est d'abord écrite, le système "mappera" à bas niveau cette page virtuelle sur une section de mémoire physique, puis l'écrira. Mais cette application elle-même n'a pas à se soucier de ces détails, elle agit comme si elle avait un accès complet à une zone virtuelle de mémoire.

Dans le cas des applications Java, ce n'est pas l'application elle-même mais Java qui se voit allouer cet espace d'adressage) et Java demande simplement un espace d'adressage énorme par défaut - la quantité demandée est calculée par rapport à la taille de la mémoire physique, mais pas parce qu'elle doit être conservatrice, mais juste pour des raisons pratiques - une application est probablement pas va vouloir assez de taille de tas pour mettre totalement un serveur à genoux, donc il fonctionne sur l'hypothèse qu'il ne le fera pas. Comme je l'ai dit ci-dessus, cela ne signifie pas que beaucoup est "alloué" ou que le système a dû dépenser beaucoup ressources le faisant.

7
thomasrutter

Imaginez que vous êtes dans le domaine du stockage de documents. Vous avez une petite installation au milieu de la ville qui stocke des boîtes de papiers et un entrepôt beaucoup plus grand en dehors de la ville avec 1000 fois l'espace. Chaque boîte a une étiquette identifiant son contenu.

L'installation en ville est la mémoire principale. L'entrepôt est l'espace disque.

Une allocation de mémoire virtuelle de 10 Go pour un nouveau processus ne signifie pas trouver de la place pour 10 milliards de boîtes pour un nouveau client. Cela signifie impression de 10 milliards d'étiquettes pour les boîtes portant des numéros d'identification contigus.

3
Russell Borogove

Ce n'est pas la quantité de mémoire physique que l'application utilise réellement. Une mémoire virtuelle utilisée par tous les processus peut avoir des ordres de grandeur supérieurs à la quantité de physique RAM sur la machine, sans aucun problème évident.

3
h22

Votre programme n'utilise PAS autant de mémoire. JVM/OS réserve cette mémoire, c'est-à-dire la limite jusqu'à laquelle votre programme peut utiliser. Aussi, comme l'une des réponses mentionne clairement. 32 bits et 64 bits n'ont rien à voir avec cela. 32 bits signifie que vous pouvez accéder à 2 ^ 32 emplacements de mémoire physique. et 64 bits signifie jusqu'à 2 ^ 64.

2
TheLostMind