trouver taille du heap java

trouver taille du heap java - Java - Programmation

Marsh Posté le 22-10-2007 à 13:48:43    

Bonjour, je dois réaliser un programme java permettant d’évaluer la taille en Ko du tas système (‘system heap’) via un algorithme approprié.
pour cela, on m'a conseillé de créer un certain nombre d'objet dont la taille est connu, et ce jusqu'a faire déborder le heap; et la taille du heap vaudrait alors le nombre d'objets crée jusqu'au débordement*la taille de l'objet en octets. Cependant, je ne vois pas comment impélemnter ceci.
Merci de votre aide.

Reply

Marsh Posté le 22-10-2007 à 13:48:43   

Reply

Marsh Posté le 22-10-2007 à 13:54:59    

http://www.google.com/search?q=java+get+heap+size

Code :
  1. long heapSize = Runtime.getRuntime().totalMemory();


---------------
HFR - Mes sujets pour Chrome - Firefox - vérifie les nouveaux posts des topics suivis/favoris
Reply

Marsh Posté le 22-10-2007 à 14:01:43    

d'accord je veux bien mais je pense vraiment pas que ce soit ce que mon prof veuille, c'est comme si tu sortais un résultat en maths sans le démontrer.
Mais merci quand même
D'autres idées?

Reply

Marsh Posté le 22-10-2007 à 14:11:20    

RV51 a écrit :

d'accord je veux bien mais je pense vraiment pas que ce soit ce que mon prof veuille, c'est comme si tu sortais un résultat en maths sans le démontrer.

ou pas du tout, c'est juste la mesure exacte.

Reply

Marsh Posté le 22-10-2007 à 19:15:28    

en fait, j'en ai parlé avec lui et il n'est pas trop d'accord avec le runtime, avez-vous quelque chose à me proposer ?
Merci.

Reply

Marsh Posté le 22-10-2007 à 19:36:21    

ca devrait donner quelque chose comme ca , mais même si je mets un grand nombre de répétition, ca ne déborde pas , pourquoi?

Code :
  1. public static void main(String[]args){
  2. for(int i=0; i<Math.pow(10, 20);i++){
  3.   LinkedList l =new LinkedList<Double>();
  4.   if(i%1000==0){
  5.    out.println("nous sommes a "+ ((i*16)/1024)+ " Ko" ); //car 1 LinkedList<Double>() fait 16 octets
  6.   }
  7.  }
  8. }


Reply

Marsh Posté le 22-10-2007 à 19:56:16    

Oula, mesurer la mémoire disponible, c'est beaucoup plus compliqué que ça.
 
Déjà se base sur un algo qui va allouer toute la mémoire jusqu'à ce que ça foire, ce n'est pas terrible comme solution. Primo, tu as le swap. Si tu débordes la dedans, ton disque dur va le sentir passer. Deuxio, dans le cas hautement improbable où tu arriverais à faire échouer un malloc(), il y tellement de trucs qui vont te péter à la gueule, que tu n'auras certainement pas le temps de voir le résultat d'un out.println().
 
Qui plus est ce n'est pas parce que tu alloues un gros bloc de mémoire, que ça en occupe autant dans la RAM physique (genre un fichier mappé, mémoire partagée, ...). La somme des parties n'est pas forcément égales au tout.
 
Bref, utilise les fonctions systèmes, parce que bon pour écrouler un système, un fork() en boucle, c'est plus efficace qu'un malloc().
 
 
 

Reply

Marsh Posté le 22-10-2007 à 20:43:52    

RV51 a écrit :

ca devrait donner quelque chose comme ca , mais même si je mets un grand nombre de répétition, ca ne déborde pas , pourquoi?

Code :
  1. public static void main(String[]args){
  2. for(int i=0; i<Math.pow(10, 20);i++){
  3.   LinkedList l =new LinkedList<Double>();
  4.   if(i%1000==0){
  5.    out.println("nous sommes a "+ ((i*16)/1024)+ " Ko" ); //car 1 LinkedList<Double>() fait 16 octets
  6.   }
  7.  }
  8. }




Il me semble que la portée de ton LinkedList se limite au bloc enntre {} du for, c'est a dire à une seule iteration. Ce qui veut dire qu'a l'iteration i+1, le linkedlist alloué a l'operation i n'est plus utilisé et donc liberé par le garbage collector. Les experts confirmeront (ou pas)...

Reply

Marsh Posté le 23-10-2007 à 09:32:16    

En premier lieu il faudrait savoir de quoi on parle.
 
Qu'est ce que tu entends par tas système (system heap) ?
 
Dans cet article, on parle de "Virtual parts" de la JVM, laquelle essayes-tu de mesurer ?

Reply

Marsh Posté le 23-10-2007 à 11:14:12    

RV51 a écrit :

ca devrait donner quelque chose comme ca , mais même si je mets un grand nombre de répétition, ca ne déborde pas , pourquoi?

Code :
  1. public static void main(String[]args){
  2. for(int i=0; i<Math.pow(10, 20);i++){
  3.   LinkedList l =new LinkedList<Double>();
  4.   if(i%1000==0){
  5.    out.println("nous sommes a "+ ((i*16)/1024)+ " Ko" ); //car 1 LinkedList<Double>() fait 16 octets
  6.   }
  7.  }
  8. }




pas du tout, allouer 16 octets consomme plus que 16octs.

Reply

Marsh Posté le 23-10-2007 à 11:14:12   

Reply

Marsh Posté le 23-10-2007 à 12:25:32    

Bidem a écrit :

En premier lieu il faudrait savoir de quoi on parle.
 
Qu'est ce que tu entends par tas système (system heap) ?
 
Dans cet article, on parle de "Virtual parts" de la JVM, laquelle essayes-tu de mesurer ?


 
l'énoncé exact c'est " Ecrire un programme Java permettant d’évaluer la taille en Ko du tas système (‘system heap’) via un algorithme approprié. Le tester à la fois sous windows et sous linux.  Conclure."
et pour ce qui de la mémoire, on a un schéma très( trop) simplifié :  
 
 -------------------
|    code area          |
 -------------------
|  initialized & non    |
|  initialized data      |
 --------------------
|   stack area          |
 --------------------
|   heap area           |
 --------------------
 
 
Taz, peux-tu être plus précis stp?  
 
Merci

Reply

Marsh Posté le 24-10-2007 à 16:23:51    

Moi, j'appelle ça un énoncé C/C++ dont le mot "C/C++" a été remplacé de manière stupide et irréfléchie par "Java".
 
Parce que quand on s'intéresse à la manière dont la mémoire de la JVM est gérée, on réalise très vite que ce schéma simplifié est complètement faux. Il correspond à la structure mémoire d'un processus dont le programme a été compilé nativement (comme avec C ou C++), mais pas du tout à celui d'un programme dont la mémoire est gérée avec un ramasse-miettes.
Par exemple, et contrairement à ce qu'on trouve dans un processus classique, dans la JVM de Sun (Hotspot), il n'y a séparation aussi nette entre le code, d'un côté, et les données, de l'autre : les classes sont des objets qui sont créés dans le tas comme tous les objets alloués par new ou désérialisés.
Ensuite, il n'y a pas un tas, mais plusieurs tas en mémoire. En fait, ça dépend même de l'algorithme de ramasse-miettes que l'on choisit en démarrant la VM (mark&sweep, incrémental, ...). Mais le plus souvent, le gestionnaire de mémoire définit plusieurs tas dits "générationnels" : par exemple, un pour les objets à courte durée de vie, un autre pour les objets à durée de vie moyenne, un 3ème pour les objets à durée de vie longue. Cela réduit fortement la fragmentation de la mémoire, et rend plus efficaces les allocations futures.
 
Et le meilleur indice du remplacement brutal de "C/C++" par "Java" dans cet énoncé, ça reste encore d'oser parler de tas "système", ce qui est totalement absurde pour une VM.
 
Bref, pour en revenir à la question posée, la première solution de brissou n'est pas mal. Elle a juste un inconvénient, c'est qu'elle ne permet de récupérer que la taille max du tas à un instant donné ; or cette taille max actuelle du tas peut évoluer au cours du temps (cf. JavaDoc de cette fonction). Pour obtenir la taille limite que le tas ne pourra jamais dépasser, ce erait plutôt Runtime.maxMemory() qu'il faut utiliser, ce qui doit correspondre à la valeur spécifiée par l'option -Xmx au démarrage de la machine virtuelle de Sun.


Message édité par BifaceMcLeOD le 24-10-2007 à 16:24:13
Reply

Marsh Posté le 25-10-2007 à 14:14:23    

Pour étayer mon post précédent, RV51, je te conseille d'écrire un petit programme Java graphique avec juste 2 boutons et une barre d'avancement (JProgressBar) : cliquer sur le premier bouton alloue un gros bloc mémoire (par exemple un tableau d'un million de caractères), et un clic sur le second bouton demande au ramasse-miettes de se déclencher (System.gc()).
Quant à la barre d'avancement, utilise un thread séparé pour la mettre régulièrement à jour (du genre toutes les 20 ou 50 millisecondes) et afficher le ratio entre la taille du tas utilisé et la taille totale du tas (en utilisant Runtime.freeMemory() et Runtime.totalMemory()). N'oublie pas que la taille totale du tas peut changer au cours du temps. Tu devrais pouvoir t'en sortir en moins de 70-80 lignes de code.
 
Et en l'exécutant, tu auras des surprises. Tu en auras encore plus selon que tu lances cette petite appli graphique (sur la JVM de Sun) avec :
 - les options -client ou -server (qui définissent, entre autres, des stratégies de gestion mémoire par défaut différentes),
 - les options -Xms20m et/ou -Xmx32m (qui servent à fixer les tailles initiale et maximale du tas, ici à respectivement à 20 Mo et 32 Mo),
 - l'option -Xincgc, voire les options -XX:+UseParallelGC, -XX:+UseParNewGC ou encore +XX:UseConcMarkSweepGC (qui sont des algorithmes de gestion mémoire différentes, utilisables pour des applications Java serveur très consommatrices en mémoire).
 
Tu auras encore d'autres surprises selon que tu lances, sur la même machine, avec un JRE 1.5 ou un JRE 6...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed