Gestion de la mémoire sous Java Composition et fonctionnement -- Transcription d'un sujet de webcast



Documents pareils
Didacticiel de mise à jour Web

HP Data Protector Express Software - Tutoriel 3. Réalisation de votre première sauvegarde et restauration de disque

ORACLE TUNING PACK 11G

Support technique logiciel HP

PARAGON SYSTEM BACKUP 2010

Séquence de découverte de SparkAngels Logiciel d entraide numérique

Service de réplication des données HP pour la gamme de disques Continuous Access P9000 XP

Module 0 : Présentation de Windows 2000

Institut Supérieure Aux Etudes Technologiques De Nabeul. Département Informatique

HP Data Protector Express Software - Tutoriel 4. Utilisation de Quick Access Control (Windows uniquement)

Conception d'applications de base de données ios plus rapides Guide Pratique FileMaker

Chapitre 1 : Introduction aux bases de données

Mises à jour des logiciels Manuel de l'utilisateur

Service d'installation et de démarrage de la solution de stockage réseau HP StoreEasy 1000/3000

Installation et Réinstallation de Windows XP

Guide de l'administrateur Citrix Personal vdisk 5.6.5

Tune Sweeper Manuel de l'utilisateur

ORACLE DIAGNOSTIC PACK 11G

Les Enseignants de l Ere Technologique - Tunisie. Niveau 1

INF2015 Développement de logiciels dans un environnement Agile. Examen intra 20 février :30 à 20:30

Mise à jour, sauvegarde et restauration de logiciels

Acronis Backup & Recovery 10 Advanced Server Virtual Edition. Guide de démarrage rapide

Brochure Optimisez les relations. HP Exstream pour les services financiers

Interface PC Vivago Ultra. Pro. Guide d'utilisation

Licences Windows Server 2012 R2 dans le cadre de la virtualisation

Le défi : L'avantage Videojet :

Module SMS pour Microsoft Outlook MD et Outlook MD Express. Guide d'aide. Guide d'aide du module SMS de Rogers Page 1 sur 40 Tous droits réservés

PC Check & Tuning 2010 Optimisez et accélérez rapidement et simplement les performances de votre PC!

Qu'est-ce que c'est Windows NT?

Didacticiel du service cartographique en cache

modélisation solide et dessin technique

Annexe de la fiche technique HP Datacenter Care - Flexible Capacity Service

PRINCIPES DE BASE DE LA SAUVEGARDE POUR LA PROTECTION DE VOS DONNÉES ET DE VOTRE ACTIVITÉ

Tutorial Ophcrack. I) Ophcrack en API. (ou comment utiliser Ophcrack pour recouvrir un mot de passe sous Windows XP et Windows Vista)

RENDRE VOS APPLICATIONS JAVA PLUS EFFICACES Ce qu'il faut savoir

portnox pour un contrôle amélioré des accès réseau Copyright 2008 Access Layers. Tous droits réservés.

Sage CRM. 7.2 Guide de Portail Client

Manuel d installation Lecteur XM3

Sage Start Saisie des collaborateurs Instructions. A partir de la version

Guide de déploiement

NETWORK & SOFTWARE ENGINEERING MANUEL D UTILISATEUR. Logiciel TIJARA. NETWORK AND SOFTWARE ENGINEERING Manuel d'utilisateur "TIJARA" 1

Architecture complète de protection du stockage et des données pour VMware vsphere

ManageEngine IT360 : Gestion de l'informatique de l'entreprise

Guide de l'utilisateur de l'application mobile

Edutab. gestion centralisée de tablettes Android

Foire aux Questions Note: Les réponses aux questions correspondent à la version Mise en route

Manuel de l'utilisateur

LA SAUVEGARDE DES DONNEES SUR LES ORDINATEURS PERSONNELS

Installation personnalisée d'oracle 10g

Manuel de l'utilisateur d'intego VirusBarrier Express et VirusBarrier Plus

Sauvegarde des bases SQL Express

Guide d'intégration à ConnectWise

Solution A La Gestion Des Objets Java Pour Des Systèmes Embarqués

Microsoft Application Center Test

Symantec Enterprise Vault

Tous les autres noms de produits ou appellations sont des marques déposées ou des noms commerciaux appartenant à leurs propriétaires respectifs.

L'appel public à l'épargne, pour quel besoin de financement? (2/3)

Structure logique. Active Directory. Forêts Arborescences Domaines Unités d'organisation

Conditions Particulières de Maintenance. Table des matières. Ref : CPM-1.2 du 08/06/2011

Technologie SDS (Software-Defined Storage) de DataCore

Seagate Technology LLC S. De Anza Boulevard Cupertino, CA 95014, États-Unis

Annexe 5. Kaspersky Security For SharePoint Servers. Consulting Team

HP OpenView AssetCenter

Java - la plateforme

Virtualisation de Windows dans Ubuntu Linux

KMnet Admin LOGICIEL COMPLET ET PERFORMANT D'ADMINISTRATION DES PÉRIPHÉRIQUES.

1. Introduction Création d'une requête...2

Nouveautés par rapport à la version Qlik Sense 1.0. Qlik Sense Copyright QlikTech International AB. Tous droits réservés.

Virtualisation des postes de travail

Guide d'installation. Release Management pour Visual Studio 2013

VRM Monitor. Aide en ligne

Traitement de texte : Quelques rappels de quelques notions de base

Projet : PcAnywhere et Le contrôle à distance.

Suite dossier d appel

MEDIAplus elearning. version 6.6

Java 7 Les fondamentaux du langage Java

Article 2 : Conseils et meilleures pratiques pour gérer un cloud privé

GUIDE DE L UTILISATEUR Recoveo Récupérateur de données

Découverte et prise en main de SWEET HOME 3D

Qu'est ce que le Cloud?

Pour valider les pré-requis nécessaires, avant d'aborder le TP, répondez aux questions ciaprès

2. Technique d analyse de la demande

Les nouveautés de LEONARDO 13

ésylog, direction technique Esylog_PeerBackup outil de sauvegarde individuelle mails & fichiers personnels documentation technique

Infrastructure - Capacity planning. Document FAQ. Infrastructure - Capacity planning. Page: 1 / 7 Dernière mise à jour: 16/04/14 16:09

Guide de configuration de SQL Server pour BusinessObjects Planning

JEU BOURSIER Séance d introduction à la plateforme de trading SaxoWebTrader. - Pour débutants -

Check-list de maintenance du système Instructions impératives pour l'utilisateur du système Dernière mise à jour 09 juin 2011

Télécom Nancy Année

Automatisation d'une Facture 4. Liste Déroulante Remises Case à cocher Calculs

MS PROJECT Prise en main. Date: Mars Anère MSI. 12, rue Chabanais PARIS E mail : jcrussier@anere.com Site :

Déduplication des données : un élément essentiel de votre stratégie de protection des données

ENT Espace de stockage

Code de bonne conduite relatif à la publicité et à l information sur les assurances-vie individuelles

Spécifications de l'offre Surveillance d'infrastructure à distance

Analyse de performance, monitoring

Maintenance de son PC

Chapitre V : La gestion de la mémoire. Hiérarchie de mémoires Objectifs Méthodes d'allocation Simulation de mémoire virtuelle Le mapping

Retrospect 7.7 Addendum au Guide d'utilisation


Transcription:

Knowledge-on-Demand HP-UX 11i : découvrez, auprès de nos laboratoires, les meilleures pratiques pour optimiser vos performances Série pour développeurs Gestion de la mémoire sous Java Composition et fonctionnement -- Transcription d'un sujet de webcast Bonjour à tous. Merci et bienvenue à tous ceux qui sont avec nous à distance aujourd'hui. Le sujet de cette session est la composition et le fonctionnement de la gestion de la mémoire sous Java. L'objet de la présentation d'aujourd'hui est d'expliquer comment fonctionnent les différentes stratégies de récupération de mémoire sous HP-UX ; il s'agit d'une première étape incontournable pour tous ceux qui s'efforcent d'analyser et d'améliorer la qualité de fonctionnement d'une application Java. Bien que la présentation ne se concentre pas sur les outils fournis par HP pour l'analyse des problèmes de fonctionnement liés à la récupération de mémoire, les connaissances que vous allez acquérir aujourd'hui sont un avant-goût essentiel de l'utilisation de tous les outils d'analyse de la récupération à venir. Il est important de bien comprendre les composants de la récupération de mémoire afin d'interpréter au mieux les données présentées par les outils et d'intervenir de manière adéquate pour optimiser votre application. Nous allons donc commencer par une courte introduction et une présentation de la gestion de la mémoire sous Java. Nous nous intéresserons ensuite aux récupérateurs de mémoire générationnels afin de vérifier que nous comprenons bien leur fonctionnement et ce qui se produit précisément lorsque votre application passe par un cycle de récupération. Ensuite, nous examinerons toutes les stratégies prises en charge dans la machine virtuelle Java de HP (JVM). Nous expliquerons, par ailleurs, les paramètres par défaut de chaque stratégie ; ceci vous aidera à cerner les parties de la zone d'allocation mémoire que vous devrez optimiser pour votre application. Enfin, nous terminerons notre séance d'aujourd'hui par un passage en revue des directives essentielles permettant d'assurer une bonne gestion de la mémoire pour votre application. Commençons par une vue d'ensemble de la gestion de la mémoire pour des applications écrites sous Java. Le dénominateur commun en matière de gestion de la mémoire sous Java est la récupération de mémoire. Vous m'entendrez beaucoup utiliser ce terme pendant la présentation d'aujourd'hui. Le grand principe derrière la gestion de la mémoire sous Java est qu'elle est gérée automatiquement par la JVM. Contrairement à C ou C++, où les développeurs doivent gérer explicitement l'allocation et la libération de la mémoire avec les commandes madloc/free ou new/delete, les développeurs Java n'ont aucune obligation spécifique ; les besoins en mémoire pour leur application sont gérés par le récupérateur de mémoire dans la

Il existe de nombreux types de récupérateurs de mémoire, chacun présentant ses propres avantages et inconvénients. Par exemple, les récupérateurs de comptage de références qui reposent sur la présence d'un compteur de référence dans l'en-tête de chaque objet. Le compteur gagne ou perd un incrément à chaque fois qu'un objet gagne ou perd une référence. Les objets ayant un compte de référence de zéro sont considérés comme «morts» et sont récupérés. Bien qu'il s'agisse d'un moyen simple et relativement rapide de gérer la mémoire, on s'aperçoit vite qu'il ne gère pas bien la réutilisation de l'espace ; par exemple, il n'effectue pas de compactage. Parmi les autres types de récupérateurs de mémoire, il y a ce qu'on appelle les récupérateurs de balayage de marque. Contrairement aux récupérateurs de comptage de références, les récupérateurs de balayage de marque mettent régulièrement à l'arrêt l'application en cours d'exécution, examinent rapidement tous les objets afin d'identifier et de marquer ceux qui ne sont plus accessibles, puis réalisent un balayage pour reprendre leur espace. Il existe une troisième catégorie de récupérateurs : les récupérateurs copieurs compacts de balayage de marque. Contrairement aux récupérateurs de balayage de marque uniquement, qui gèrent la mémoire de l'application dans un seul espace dédié, les récupérateurs copieurs divisent l'espace où des objets sont affectés en deux zones distinctes. L'une d'elle fait office de récupérateur normal de balayage de marque. Cependant, au lieu de se contenter d'identifier et de supprimer les objets morts, il copie aussi tous les objets vivants ou survivants dans le second espace. La copie séquentielle des objets vivants vers ce second espace a pour effet d'éliminer la fragmentation et de compacter la mémoire. Après la copie, l'application repart et l'allocation des nouveaux objets se fait dans l'espace compacté. Le récupérateur copie les objets survivants en alternance dans les deux espaces distincts. Les récupérateurs de balayage de marque et compacts de balayage de marque constituent ce qu'on appelle des récupérateurs «stop-the-world» ; ils doivent arrêter l'application en cours pour être en mesure de marquer et de balayer. Il existe une quatrième catégorie de récupérateurs de mémoire appelés les récupérateurs simultanés de balayage de marque. Ils s'efforcent de réduire le délai pendant lequel une application est arrêtée pour les besoins de la récupération de mémoire. Ils sont appelés les récupérateurs simultanés. En fait, ils ne sont que partiellement simultanés car ils ont aussi besoin d'arrêter ou de mettre en pause l'application en cours. Mais la durée de la pause est très courte. Le récupérateur de mémoire fourni avec la JVM de HP est un récupérateur copieur générationnel. Il s'agit essentiellement d'un récupérateur de mémoire compact de balayage de marque. Néanmoins, contrairement aux récupérateurs compacts de balayage de marque habituels, il sépare la zone d'allocation mémoire Java en plus de deux espaces. Examinons d'un peu plus près les récupérateurs de mémoire générationnels et efforçons-nous de comprendre leur fonctionnement. Notre récupérateur de mémoire générationnel divise la zone d'allocation mémoire Java en cinq espaces ou générations différentes. Il y a une nouvelle/jeune génération qui est elle-même divisée en un «éden» et deux espaces de survie appelés «TO» et «FROM», un ancien espace et un espace permanent indépendant. Nous divisons la zone d'allocation mémoire de cette manière car nous savons, par l'examen d'un large éventail d'applications, que la plupart des objets ont une courte vie et que le coût de la réalisation d'un cycle de récupération est directement proportionnel au nombre d'objets devant être examinés. En d'autres termes, plus il y

a d'objets à marquer et à balayer, plus le coût est élevé. Nous nous efforçons d'optimiser le coût de la récupération en accélérant les cas courants, soit en accélérant le coût du marquage et du balayage des objets dont l'allocation est récente dans une petite portion de la zone d'allocation mémoire Java (dans la nouvelle/jeune génération). La taille de la zone d'allocation mémoire est contrôlée par deux drapeaux JVM ou options de ligne de commande (-Xms et Xmx). La commande «-Xms» contrôle la taille initiale de la zone d'allocation mémoire et la commande «Xmx» contrôle sa taille maximale, comme nous le montrons ici. Lorsque ces deux drapeaux JVM ne présentent pas la même valeur, la JVM initialisera la zone d'allocation mémoire en fonction de la valeur établie par la commande «Xms», puis agrandira la zone d'allocation mémoire progressivement si nécessaire jusqu'à ce que la taille maximale soit atteinte. La taille de la nouvelle/jeune génération peut également être déterminée sur la ligne de commande ; il suffit de spécifier «Xmn». La taille de l'espace permanent peut être définie en précisant «XX:PermSize» sur la ligne de commande. La nouvelle/jeune génération est là où résident tous les objets nouvellement créés. Les objets survivant à la récupération (c.-à-d. les objets durables) sont copiés dans l'ancienne génération. L'espace permanent est mis de côté pour le stockage des renseignements sur les catégories de l'application qui sont utilisées directement par la JVM. Comme nous l'avons déjà mentionné, les espaces «To» et «FROM» sont appelés les espaces de survie. Leur taille est définie comme une proportion de la taille de la nouvelle génération. Le drapeau de ligne de commande Java «XX:SurvivorRatio» définit la taille d'un espace de survie par rapport à la taille de l'éden. Une autre ligne de commande importante est «XX:MaxTenuringThreshold». La valeur associée à ce drapeau de ligne de commande précise l'âge de l'objet survivant, soit le nombre de fois qu'il survivra à une récupération mineure. Tout ceci deviendra clair à mesure que nous examinerons le fonctionnement interne des récupérateurs de mémoire générationnels dans la série suivante de diapositives. Compte tenu de la précédente description de la zone d'allocation mémoire, il deviendra clair qu'il existe deux types de récupération ayant deux coûts très différents : une récupération mineure correspondant à la nouvelle/jeune génération devenant «pleine» et une récupération majeure qui est déclenchée lorsque la zone d'allocation mémoire entière est «pleine». Bien, maintenant que nous comprenons comment le récupérateur de mémoire générationnel divise la zone d'allocation mémoire, examinons son fonctionnement d'un peu plus près. Comme nous l'avons déjà dit, tous les nouveaux objets sont initialement affectés à la nouvelle génération. Plus précisément, tous les nouveaux objets sont affectés directement à la zone appelée «éden» de la nouvelle génération. Dans la vue suivante de la zone d'allocation mémoire Java, nous présentons plusieurs objets «rouges» affectés à l'éden suite à l'exécution d'une application pendant un certain temps. Pour les besoins de cet exemple, supposons que nous avons établi notre seuil d'occupation à une valeur basse de seulement 2. Notre application est donc en cours d'exécution depuis un moment et elle a créé de nouveaux objets qui ont tous été placés initialement dans l'éden. Que se passera-t-il quand l'éden sera plein?

Lorsque l'éden est plein, la JVM met l'application en pause (c'est ce qu'on a aussi appelé «stop-the-word» quand nous décrivions les différents types de récupérateurs de mémoire) Après avoir mis l'application Java en pause, la JVM réalise une itération sur tous les objets dans l'éden et marque ceux qui sont vivants (ceux qui sont référencés par d'autres objets de l'application). Les objets vivants dans notre vue de la zone d'allocation mémoire sont indiqués par une flèche pointant dans leur direction. Que se passe-t-il une fois que la JVM a marqué tous les objets vivants? Tous les objets vivants sont ensuite copiés dans l'un des deux espaces de survie. Les objets demeurant dans l'éden une fois que les objets vivants ont été copiés dans un espace de survie sont ceux que nous considérons comme «morts». Ce sont les objets que nous devons récupérer. Les objets morts qui étaient dans l'éden sont récupérés ou évacués par le biais d'une récupération mineure qui n'est appliquée qu'à une petite portion de la zone d'allocation mémoire, à savoir l'éden. Les objets vivants qui ont survécu à l'évacuation (les objets ayant été copiés dans l'un des espaces de survie) recevront un âge de 1 ; cet âge représente leur seuil d'occupation. Une fois l'évacuation terminée, la JVM remet en route l'application interrompue et de nouveaux objets sont créés dans la nouvelle/jeune génération. Ces nouveaux objets, présentés ici sous forme de blocs jaunes, finissent par remplir l'éden de la nouvelle génération. Que se passe-t-il ensuite? La JVM met à nouveau l'application en pause et se prépare à réaliser une nouvelle récupération mineure (ou évacuation) Tous les objets vivants se trouvant dans l'éden «ET» le premier espace de survie sont marqués, puis copiés dans le second espace de survie et leur âge ou seuil d'occupation est actualisé en conséquence. Il faut noter qu'après une évacuation ou une récupération mineure, l'éden et un espace de survie se retrouvent toujours vides. Remarquez aussi que l'un des objets a survécu à deux récupérations mineures jusqu'à présent et, par conséquent, il a atteint le seuil d'occupation. Ce qui signifie que si l'objet demeure vivant après une troisième récupération mineure, il devra être transféré vers l'ancienne génération. Bien. Notre seconde récupération ou évacuation est terminée. La JVM réactive l'application et de nouveaux objets sont replacés dans l'éden.

Ces nouveaux objets sont présentés ici sous forme de blocs bleu clair dans l'éden. Une fois l'éden rempli, la JVM met l'application en pause pour la troisième fois. Tous les objets vivants sont identifiés et marqués, puis tous les objets ayant déjà atteint leur seuil d'occupation sont d'abord copiés dans l'ancien espace. Ce que nous voulons montrer ici, c'est qu'un objet ayant déjà survécu à trois évacuations ou récupérations mineures est dorénavant placé dans l'ancien espace. À partir de maintenant, cet objet sera considéré comme durable et ne sera plus balayé ou copié lors de la prochaine évacuation. Après la copie de l'objet durable dans l'ancien espace, tous les objets vivants dans l'éden et dans l'un des espaces de survie sont ensuite identifiés et copiés dans le second espace de survie vide. Et comme auparavant, l'âge des objets survivants est actualisé. L'évacuation supprime tous les objets morts restants dans l'éden et l'un des deux espaces de survie. La JVM relance alors l'application et de nouveaux objets sont affectés à la nouvelle/jeune génération. Après un certain temps de fonctionnement, l'ancienne génération devient presque pleine et l'éden est plein. Lorsque cela se produit, la JVM stoppe l'application encore une fois et lance un cycle de récupération majeure (ou récupération complète). Lors d'un cycle de récupération majeure, tous les objets de la zone d'allocation mémoire (ceux du nouvel/jeune espace ainsi que ceux de l'ancien espace) sont balayés et marqués. Le récupérateur de mémoire supprime alors tous les objets morts et compacte l'ancien espace comme on vous le montre ici. Les récupérations majeures ou complètes sont très coûteuses comparativement aux récupérations mineures, principalement parce qu'elles doivent traiter tous les objets de la zone d'allocation mémoire et qu'elles ont la tâche supplémentaire de compacter l'ancien espace. Nous comprenons maintenant bien comme fonctionnent les récupérateurs de mémoire compacts de balayage de marque générationnels. Cependant, avant de passer à l'examen des composants de toutes les stratégies de récupération prises en charge dans notre JVM, intéressons-nous à un cas particulier et expliquons comment la JVM va le traiter en interne.

Dans ce cas particulier, après le remplissage de la nouvelle génération, nous pourrions nous retrouver dans le cas où tous les objets de l'éden et d'un espace de survie sont vivants. Une évacuation normale tenterait de copier tous les objets vivants dans le second espace de survie, comme nous le montrons ici. Ce n'est clairement pas possible dans le cas présent. Pour être en mesure de gérer ce type de cas particuliers, la JVM réserve, par défaut, une portion de l'ancien espace d'une taille équivalente à celle de l'éden plus un espace de survie. Cet espace est presque entièrement gâché, principalement parce qu'il est rare que tous les objets de l'éden et d'un espace de survie demeurent vivants après une récupération mineure. Si vous savez que votre application ne nécessite pas cette condition, vous pouvez réduire ou supprimer complètement la quantité d'espace réservé dans l'ancienne génération pour la gestion de ce type de cas. Vous le faites en précisant «XX:MaxLiveObjectEvacuationRatio» ; ce qui vous permet d'indiquer le pourcentage de la taille de l'ancienne génération à mettre de côté ou en précisant «Xoptgc», ce qui ne réserve aucun espace de l'ancienne génération pour ce type de cas. N'oubliez pas que la maximisation de la taille de l'ancienne génération présente l'avantage de retarder ou de réduire le nombre des récupérations complètes coûteuses. Examinons maintenant les composants des stratégies de récupération prises en charge sous HP-UX, toutes mises en œuvre, pour la plupart, sous forme de récupérateurs de mémoire compacts de balayage de marque générationnels et fonctionnant de la manière que ce que nous avons déjà expliqué. Il existe des différences dans la façon dont la stratégie de balayage de marque simultanée fonctionne et nous les soulignerons quand nous examinerons cette stratégie. La machine virtuelle Java (JVM) sous HP-UX prend en charge quatre stratégies de récupération différentes : une stratégie de récupération en série à un thread, une stratégie de récupération parallèle de nouvelle génération à haut débit, une stratégie de récupération de nouvelle et ancienne générations parallèle à haut débit et une stratégie de récupération de balayage de marque principalement simultanée à pause courte. Le fait d'avoir différentes stratégies indique qu'il n'est pas idéal d'avoir une seule stratégie de récupération fonctionnant pour tous les types d'applications. Voyons comment chacune de ces stratégies est mise en œuvre. La stratégie de récupération en série peut être activée en précisant «XX:+UseSerialGC» sur la ligne de commande Java. Avant JDK 1.4.2, c'était la stratégie de récupération par défaut sur nos plates-formes HP-PA et Integrity. Comme nous le montrons ici, les récupérations mineure et majeure n'ont qu'un seul thread avec cette stratégie. La seconde stratégie de récupération est la stratégie de récupération parallèle de nouvelle génération. Elle était proposée dans les versions ultérieures de JDK 1.4.1. Elle est devenue la stratégie de récupération par défaut sur les serveurs possédant 2 processeurs ou plus fonctionnant sous JDK 1.4.2.

Les utilisateurs peuvent activer explicitement cette stratégie de récupération en précisant «XX:+UseParNewGC» sur la ligne de commande Java. Dans le cadre de la stratégie de récupération parallèle de nouvelle génération à haut débit, les évacuations (ou récupérations mineures de la nouvelle génération) sont effectuées en parallèle. La récupération de l'ancienne génération (lorsqu'une récupération majeure ou complète est lancée) demeure à un seul thread de la même manière qu'avec une stratégie de récupération en série. Précisez «XX:+UseParallelOldGC» sur la ligne de commande Java pour activer une récupération parallèle à haut débit où les deux évacuations (ou récupérations mineures) ainsi que les récupérations majeures de l'ancienne génération sont effectuées en parallèle sur les machines dotées de 2 cœurs ou plus. Nous expliquerons comment contrôler le nombre de threads de récupération parallèle quand nous aborderons les paramètres par défaut des stratégies dans le chapitre suivant. Précisez «XX:+UseConcMarkSweepGC» sur la ligne de commande Java pour activer une stratégie de récupération simultanée de balayage de marque à pause courte dans notre JVM. Cette stratégie utilise un récupérateur à plusieurs threads de jeune génération et un récupérateur d'ancienne génération essentiellement simultané à pause courte. Le récupérateur d'ancienne génération est essentiellement simultané parce qu'il comprend deux pauses extrêmement courtes de type «stop-the-world», comme nous le montrons ici. La phase simultanée de cette stratégie est un peu compliquée ; elle comporte 4 phases principales. Comme nous vous le montrons ici, la phase 1 met l'application en pause pendant un cours moment et fait appel à un seul thread pour réaliser un marquage initial ; cette phase de marque initiale identifie un sous-ensemble de tous les objets vivants. Lors de l'examen du résultat de verbosegc avec nos outils, la pause lors de cette phase peut être identifiée sous le titre STW 1, qui est l'abréviation de «Stop The World 1». Après l'identification du sous-ensemble initial des objets vivants, la JVM relance l'application et fait appel à un thread simultané afin d'identifier tous les objets vivants accessibles à partir de l'ensemble d'objets vivants identifiés lors de la phase de marque initiale. Cette phase réalise également une récupération préalable qui constitue en fait un balayage proactif de tous les objets mis à jour lors de la phase de marque simultanée. La récupération préalable a pour but de raccourcir la durée de la pause qui sera imposée en phase 3. Au cours de la phase 3, la JVM met à nouveau l'application en pause et fait appel à de multiples threads afin d'effectuer un nouveau marquage parallèle rapide. L'objectif du nouveau marquage est d'identifier le plus grand nombre d'objets vivants manqués lors de la phase de marque simultanée (n'oubliez pas que l'application tourne toujours et continue de créer des objets au cours de la phase de marque simultanée). Lors de l'examen des données verbosegc avec nos outils, cette phase peut être identifiée sous le titre STW 2 («Stop The World 2»)

Après la phase de nouveau marquage parallèle, la JVM relance l'application pour la seconde fois et fait appel à un seul thread simultané pour le balayage de tous les objets morts. Nos outils actuels n'ont aucun moyen de voir comment les différentes phases CMS «stop-the-world» sont liées à l'utilisation de la zone d'allocation mémoire. Pour être en mesure de le faire, je superpose, en général, la vue de l'utilisation de la zone d'allocation mémoire avec la vue de la durée, comme vous le voyez ici. En alignant l'axe temporel des deux vues, vous êtes en mesure de voir clairement ce qui se produit dans la zone d'allocation mémoire Java lors de chaque phase. Ceux d'entre vous ayant commencé à utiliser JDK 6 doivent savoir qu'il existe deux nouvelles stratégies CMS. Tout d'abord, les utilisateurs de JDK 6 sont en mesure d'indiquer de multiples threads de balayage simultané en ajoutant «XX:ParallelCMSThreads» sur la ligne de commande Java. Cela permet d'accélérer considérablement le récupérateur de mémoire simultané de balayage de marque lorsqu'il est lancé sur des serveurs à cœurs multiples. Dans JDK 6 également, le traitement par défaut de la récupération de mémoire explicite (il s'agit, par exemple, d'appels à System.gc() de l'intérieur de l'application) peut maintenant être contourné afin de faire appel à une récupération CMS à pause courte au lieu de la récupération complète de mémoire si coûteuse, à l'aide d'un compactage coûteux de l'ancien espace. Cette nouvelle fonctionnalité peut être activée en ajoutant «XX:+ExplicitGCInvokesConcurrent» sur la ligne de commande Java. Un autre changement dans JDK 6 affectant directement le récupérateur CMS est lié à la façon dont l'occupation et les espaces de survie sont traités. Avant JDK 6, la spécification de la stratégie de récupération de mémoire CMS avait pour conséquence essentielle de désactiver les espaces de survie ; en fait, en spécifiant la CMS, le taux de survie était établi à 1 024, ce qui désactivait effectivement les espaces de survie en les rendant extrêmement petits. Ceci avait pour effet de fixer les objets prématurément et d'augmenter la pression sur l'ancienne génération. Tout d'abord, avec JDK 6, les espaces de survie sont réactivés, ce qui permet aux utilisateurs de les optimiser si nécessaire. Avant de conclure le débat sur le balayage de marque simultané, nous devons expliquer comment la «garantie de jeune génération» est traitée lorsque la CMS est spécifiée. Souvenez-vous, avec n'importe lequel des récupérateurs de mémoire non simultanés, si vous ne disposiez pas de suffisamment d'espace réservé dans l'ancienne génération pour gérer les cas où tous les objets de la nouvelle génération survivraient à une récupération mineure, la JVM se fermait en affichant une erreur liée à une mémoire insuffisante. Cependant, grâce à la CMS, lorsque cela se produit, le récupérateur de mémoire tente une récupération mineure de dernier recours afin de vérifier si des objets sont morts depuis la dernière tentative de transfert. Si cette dernière tentative ne permet pas de libérer suffisamment d'espace dans l'ancienne génération, le récupérateur de mémoire lance alors une importante récupération complète de l'ancienne génération, suivie d'un compactage. Et, si ceci ne parvient pas non plus à libérer assez d'espace, la JVM se ferme alors en indiquant une erreur liée à une mémoire insuffisante. Nous allons ensuite nous intéresser aux paramètres par défaut de chaque stratégie de récupération de mémoire afin de mieux comprendre comment le récupérateur se comporte si nous ne sélectionnons aucun de ces paramètres par défaut.

Si aucun paramètre de récupération de mémoire n'est spécifié sur la ligne de commande, la taille initiale de la zone d'allocation mémoire Java sera automatiquement établie à un soixante-quatrième de la mémoire physique totale disponible dans la machine, sans dépasser 1 Go (qui serait la limite). De la même manière, la taille maximale de la zone d'allocation mémoire Java serait automatiquement établie à un quart de la mémoire physique totale disponible dans la machine, qui serait également limitée à 1 Go. Lorsqu'on a affaire à des machines dotées de plus de 2 cœurs (ou processeurs), la nouvelle stratégie de récupération de mémoire parallèle est choisie par défaut. La JVM active aussi par défaut la stratégie de taille adaptative, qui tente effectivement de faire varier la taille de l'éden et des espaces de survie, ainsi que les seuils d'occupation, en fonction d'une heuristique JVM interne. Nous essaierons ensuite de comprendre comment la JVM établit le nombre de threads parallèles de récupération de mémoire lorsque l'un des récupérateurs de débit est activé. Si le serveur où Java est déployé possède un maximum de 8 cœurs (ou processeurs), alors la JVM lance autant de threads parallèles de récupération de mémoire qu'il y a de cœurs dans la machine. Dans les cas où Java est lancé sur des serveurs dotés de plus de 8 cœurs, le nombre de threads parallèles de récupération de mémoire est établi par la JVM à l'aide de la formule présentée ici. La JVM utilise le même mécanisme pour déterminer le nombre de threads parallèles de récupération de mémoire pour le récupérateur CMS à pause courte. Dans le cas du récupérateur CMS à pause courte, la JVM redimensionne automatiquement par défaut les espaces de la nouvelle génération. Et, comme nous l'avons déjà dit, avec JDK 5.0 et les versions antérieures, la JVM s'efforce de transférer prématurément les objets pour tenter d'écourter les pauses causées par les récupérations mineures. Les paramètres automatiques de la JVM sont affectés si les utilisateurs indiquent des valeurs explicites de taille initiale ou maximale de la zone d'allocation mémoire, ou s'ils indiquent un rapport de survie ou un seuil d'occupation explicite. Maintenant que nous comprenons bien comment fonctionnent les récupérateurs de mémoire générationnels, ainsi que les différentes stratégies de récupération de mémoire et comment sont établis leurs paramètres par défaut, nous allons consacrer un peu de temps à la qualité de la récupération de mémoire : Quand utiliser une stratégie de récupération de mémoire plutôt qu'une autre? Quelles sont les consignes générales garantissant une bonne qualité de fonctionnement de la récupération de mémoire avec votre application? De plus, nous aborderons rapidement les outils Java d'analyse des performances dont vous disposez gratuitement sous HP-UX. Parallèlement à votre connaissance approfondie du fonctionnement interne de notre récupérateur de mémoire, vous éprouvez maintenant un plus grand intérêt pour les outils et le type de vision qu'ils procurent dans la

localisation des goulets d'étranglement de votre application. Je vous encourage à activer le profilage JVM et à utiliser les outils pour examiner à la fois votre application et la machine virtuelle Java. Ceci vous permettra de vous faire une bonne idée de l'endroit où sont localisés les problèmes et de décider de la manière de les résoudre. Commençons par les consignes générales relatives au bon dimensionnement de la zone d'allocation mémoire Java. L'objectif ici devrait être de minimiser le nombre de récupérations complètes de mémoire coûteuses et de vérifier que les objets éphémères ne soient pas affectés prématurément. Par conséquent, conservez un seuil d'occupation élevé et assurez-vous que votre nouvelle génération est correctement dimensionnée. Une nouvelle génération trop grande peut entraîner des pauses longues du fait de récupérations mineures anormalement longues. De plus, une nouvelle génération trop petite pourrait entraîner le remplissage trop rapide de l'ancien espace, ce qui conduirait à de fréquentes récupérations complètes de mémoire coûteuses. Par ailleurs, assurez-vous que vous évitez des récupérations complètes de mémoire inutiles et coûteuses en raison d'appels explicites à System.gc() ou Runtime.gc() de l'intérieur de votre application. Vous pouvez indiquer «XX:+DisableExplicitGC» sur la ligne de commande Java afin d'obliger la JVM à ignorer les appels à ces deux routines de récupération explicites. Ici encore, servez-vous des outils pour savoir si votre application fait appel à ces routines. Par ailleurs, si votre application utilise RMI, indiquez la valeur la plus haute possible pour l'intervalle de récupération de mémoire pour le serveur et pour le client, comme on vous le montre ici. Dans le cas contraire, une récupération complète et coûteuse de la mémoire sera effectuée toutes les 60 secondes. Appliquez la meilleure stratégie de récupération de mémoire en fonction du type d'application utilisé. Si vous disposez d'une petite application fonctionnant sur une petite machine, il serait peut-être préférable d'utiliser le récupérateur de mémoire en série à un seul thread. Si, d'un autre côté, vous disposez d'une grande application orientée débit fonctionnant sur un système doté de plus de 2 processeurs, alors utilisez l'un de nos récupérateurs de débit parallèles. Et si votre application est très sensible aux pauses imposées par la récupération de mémoire, il serait peut-être préférable d'utiliser le récupérateur simultané de balayage de marque. Si l'application fonctionne avec Montecito Hyper Threading activé (ce qui est désormais possible avec la version 11i v3), pensez à déterminer manuellement un nombre de threads parallèles de récupération de mémoire égal au nombre de cœurs physiques de la machine. Pensez aussi à désactiver explicitement le lien entre les threads de tâche de récupération de mémoire et les processeurs en ajoutant «XX:-BindGCTaskThreadsToCPUs» sur la ligne de commande Java. Si vous n'êtes pas certain de ce que fait votre application ou si vous ne savez pas exactement quelle valeur modifier ensuite, pensez à télécharger et exploiter nos outils d'analyse des performances.

Les outils apporteront des réponses immédiates à vos questions de base. Par exemple : Que font les différents threads de l'application? Quels threads fonctionnent lentement? À quoi chaque thread passe-t-il le plus de temps? Le problème que vous voyez est-il causé par le récupérateur de mémoire ou par autre chose? Une fois que vous aurez identifié le problème d'une manière générale, les outils vous permettront de rentrer au cœur de l'application et de localiser la source exacte du ralentissement. Ce qui nous amène à la fin de la présentation d'aujourd'hui. Mais avant de conclure, résumons les points clés : Point clé numéro 1- Assurez-vous que vous comprenez parfaitement le fonctionnement de chacune de nos stratégies de récupération de mémoire. Point clé numéro 2- Comprenez les paramètres par défaut de chaque stratégie. Point clé numéro 3- Appliquez la stratégie de récupération de mémoire adaptée au type de charge de travail dont il est question. Point clé numéro 4- Suivez les consignes générales d'optimisation. Et quand votre application ne fonctionne pas bien, utilisez les outils afin d'identifier et de résoudre rapidement tous les problèmes de performances. La présentation d'aujourd'hui est terminée. Pour de plus amples informations, visitez le site suivant : www.hp.com/go/kod 2008 Hewlett-Packard Development Company, L.P. Les informations contenues dans le présent document sont sujettes à modification sans préavis. Les seules garanties applicables aux produits et services HP sont celles énoncées dans les déclarations de garantie expresses qui accompagnent lesdits produits et services. Aucun élément du présent document ne peut être interprété comme constituant une garantie supplémentaire. HP ne saurait être tenue responsable des erreurs ou omissions de nature technique ou rédactionnelle contenues dans le présent document.