Exercice 1.4 : Résolution du goulot d'étranglement d'unité d'exécution
Avant de commencer, vous devez terminer l'Exercice 1.3 :
Identification d'un goulot d'étranglement d'unité d'exécution.
Pour localiser le blocage dans votre code, vous pouvez utiliser le diagramme de séquence UML2 (vues UML2 Object Interactions et UML2 Thread Interactions) et la ressource de profilage Pile d'appels du Moniteur de profilage en plus de la fenêtre Vue unité d'exécution.
Pour résoudre ce blocage, i faut d'abord identifier les appels de méthode et les objets impliqués dans l'incident :
- Dans la fenêtre Vue unité d'exécution, repérez la première unité d'exécution philo* présentant un état "Attente de verrouillage". Placez votre curseur sur le segment correspondant. L'infobulle identifie le verrouillage attendu par l'unité d'exécution : Fork.<id number>.
- Cliquez à l'aide du bouton droit de la souris sur la ressource de profilage de l'exécution, puis sélectionnez Ouvrir avec > UML2 Object Interactions. La vue Diagramme de séquence UML2 s'ouvre et affiche les interactions d'objet.
- Dans le diagramme de séquence, faites défiler la vue pour trouver Fork.<id number>, puis sélectionnez-le.
- Recherchez une flèche horizontale qui relie les unités d'exécution philo* au verrouillage Fork.<id number>. Ces flèches montrent les interactions entre les objets ; la première interaction entre ces deux objets indiquera que l'unité d'exécution philo* aura acquis Fork.<id number>. Ces flèches sont nommées getName.
- Cliquez deux fois sur getName. Dans Vue unité d'exécution, le trait vertical Heure actuelle se déplace pour montrer ce qui s'est passé dans tout le programme lorsque getName a été appelé. Vous pouvez constater que la demande a abouti, puisque l'unité d'exécution philo* qui a fait cette demande ne présente pas l'état "Attente de verrouillage".
- Dans le diagramme de séquence, cliquez de nouveau deux fois sur Fork.<id number>, puis faites défiler jusqu'à voir une demande getName émise par une autre unité d'exécution philo*.
- Cliquez deux fois sur cette instance de getName. L'indicateur Heure actuelle montrera que l'unité d'exécution philo* qui a fait cette demande n'a pas obtenu Fork.<id number> et qu'elle indique l'état "Attente de verrouillage".
Dans cet exemple, le problème vient d'une demande de processus parallèle de traitement effectuée par une autre unité d'exécution. Contrôlez d'autres unités qui se terminent avec l'état "Verrouillage en attente" pour vérifiez que cette hypothèse se vérifie dans d'autres exemples.
Essayons maintenant d'identifier la méthode qui est à l'origine de l'incident :
- Cliquez à l'aide du bouton droit de la souris sur la ressource de profilage de l'exécution, puis sélectionnez Ouvrir avec > UML2 Thread Interactions. La vue Diagramme de séquence UML2 s'ouvre et affiche les interactions d'unité d'exécution.
- Dans le Moniteur de profilage, développez votre ressource de profilage, puis l'entrée Analyse d'unité d'exécution et enfin l'entrée Pile d'appels.
- Dans la fenêtre Vue unité d'exécution où sont affichés les noms des unités d'exécution, cliquez deux fois sur la première unité philo* qui indique l'état "Verrouillage en attente". Notez que la vue des interactions d'unité change pour n'afficher plus que les informations de l'unité concernée.
- Lisez ces informations jusqu'à la fin, puis cliquez deux fois sur la dernière méthode exécutée par l'unité : la méthode run. La pile d'appels du Moniteur de profilage affiche tous les appels en même temps.
- Dans la pile d'appels, notez que l'unité d'exécution qui détient le verrouillage a appelé la méthode Sleep dans Philosopher.java ; ou qu'elle attend aussi un verrouillage et que par conséquent, elle est inactive.
- Contrôlez les autres unités d'exécution qui se terminent avec l'état "Verrouillage en attente" ; la méthode Sleep de Philosopher.java apparaît souvent dans la pile d'appels et il se pourrait qu'elle soit à l'origine de l'incident.
A ce stade, nous suspectons donc la méthode Sleep d'être à l'origine de l'incident. Examinons le code :
- Dans la pile d'appels, cliquez à l'aide du bouton droit de la souris sur une instance de Sleep(int) void [Philosopher.java], puis sélectionnez Ouvrir source. La source s'ouvre dans l'éditeur, à l'emplacement de la classe Sleep.
- Examinez le code. Notez que la méthode Sleep est appelée depuis la méthode run. Il y a d'bord un appel vers trace, qui imprime le message "got left...", puis un appel vers Sleep. En mettant l'appel de Sleep en commentaire, nous pourrions peut-être éviter le blocage.
- Mettez Sleep en commentaire.
- Sélectionnez Fichier > Sauvegarder.
Maintenant, profilez à nouveau votre programme.
Cette fois-ci, il s'exécute sans blocage et affiche le message suivant dans la console :
HeadWaiter reports all philosophers have finished dining normally
La fenêtre Vue unité d'exécution et les autres vues vous montrent ce qui se passe au niveau des unités au cours de l'exécution de votre programme. Vos connaissances du programme vous permettent désormais d'effectuer une analyse et de résoudre les blocages éventuels.
Terminez ce tutoriel en passant en revue les objectifs de formation, dans la
section Résumé.