Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
En pratique : Présentation et utilisation de Hieronymus
(Article écrit par Mathias Parnaudeau - septembre 2010)
|
|
Hieronymus : mais qui es-tu ?
Un nom et une fonctionnalité qui laissent perplexe ! Lors du week-end Amigâteries, début mars 2010, Daff m'a fait remarquer qu'il
serait bon d'avoir un article décrivant à quoi sert Hieronymus, ce qu'il fait et comment il le fait. Communiquer plus sur lui devint,
après coup, une évidence. L'autre remarque de Daff (décidément toujours pertinent) fut que le mieux placé pour en parler... était
son créateur. Il faut vraiment tout m'expliquer ! En retour, c'est donc moi qui vais tout vous raconter.
Le chasseur de lenteurs
Parmi les outils de développement, il en existe qui sont destinés à traquer les goulots d'étranglement d'un programme, à comprendre
où il passe son temps. On les appelle des profileurs, comme les policiers chargés d'analyser des faits et des comportements pour
comprendre comment fonctionne un criminel. Sauf qu'ici, la cible, c'est un programme lent ! Un programme peut déjà lui-même collecter
des informations à publier lorsqu'il se termine, incrémentant des compteurs ou additionnant des durées. Par exemple, dans Sonix,
qui contrôle une webcam, je mesure le temps mis pour récupérer une image, pour la décoder, pour l'afficher. Il ne sert à rien de
vouloir optimiser la fonction de décodage si le transfert est déjà 20 fois plus lent. Le résultat ne sera pas visible. La collecte
manuelle de ces informations reste fastidieuse.
Dans la suite d'outils associés à gcc, il existe gprof depuis des années. L'exécution d'un programme compilé avec des options
particulières permettra, automatiquement cette fois-ci, de savoir combien de fois chaque fonction a été appelée, pendant combien
de temps, etc. C'est déjà pratique mais il faut recompiler le code spécifiquement pour collecter des données et cela peut avoir une
influence sur le comportement du programme, bien que si quelques fonctions sont responsables de la majorité du temps passé, elles
seront détectées.
C'est statistique, mon cher Harry
Hieronymus est un profileur statistique simple dont le fonctionnement de base repose sur un outil Linux appelé oprofile. Le principe
repose sur l'abonnement à une source d'interruption qui va périodiquement suspendre le programme en cours dans le système pour
donner la main à un "handler" d'interruption. Ainsi, à une fréquence donnée (50 fois par seconde dans notre cas), cette fonction
handler est appelée avec en paramètre un contexte d'interruption indiquant l'état du processeur au moment où l'interruption est
survenue. Ce contexte (voir l'include "exec/interrupts.h") contient les valeurs de tous les registres du processeur et notamment
celui qui nous intéresse directement pour la fonctionnalité de base : le pointeur d'instruction (IP). Il indique à quelle adresse
le système devra sauter quand l'interruption aura été traitée pour reprendre l'exécution normale du programme suspendu.
Cinquante fois par seconde, Hieronymus sauve dans un tableau d'échantillons la valeur du pointeur d'instruction. Pour chacune de
ces valeurs, une autre fonction du système permet à partir de cette adresse de déterminer le processus concerné et à quelle position
("offset") on se trouve dans le code du programme.
La dernière étape consiste à trouver à quelle fonction la position correspond. Pour cela, il n'y a pas d'autre solution que de trouver
l'exécutable (au format ELF) et de chercher à quel symbole la position appartient. Par symbole, on entend dans notre cas le nom de la
fonction associée.
Après ces indications techniques, prenons un peu de distance pour mieux comprendre le fonctionnement général. Avec une durée
d'échantillonnage suffisamment grande, on sait déterminer la proportion du temps passé dans chacun des programmes du système
mais on obtient aussi le profil d'exécution d'un programme, c'est-à-dire le nombre de fois où il se trouvait dans telle ou telle
fonction quand il a été interrompu. On appelle cela du profilage statistique : si de manière périodique, dans 60% des cas où on
interrompt un programme, on constate qu'il se trouve dans une fonction donnée, on peut dire que le programme passe 60% de son temps
dans cette fonction (à traiter de toute urgence !).
Avantages, usage et résultats
Par rapport à un outil comme gprof, Hieronymus ne demande aucune modification du programme, il suffit que ce dernier ait été compilé
avec l'option de débogue classiquement utilisée en cours de développement, afin d'avoir accès aux symboles cités plus haut. Il
n'est donc pas intrusif.
Un autre avantage est qu'il trace ce qui est en cours d'exécution, ce qui inclut aussi les bibliothèques dynamiques, contrairement
à gprof. Cela donne une idée pour savoir si un problème vient de la lenteur d'un algorithme dans le programme ou si ce dernier
appelle trop souvent des fonctions système liées au graphisme, au réseau, etc.
Enfin, Hieronymus est simple à utiliser. Il n'y a qu'à le lancer, via un Shell, sans aucun paramètre. Le seul argument actuellement
disponible dans Hieronymus est le temps d'acquisition (défaut = 8 secondes) que l'on peut modifier avec "hieronymus duration=20" pour
par exemple passer à 20 secondes. Il va alors collecter tranquillement les informations sur l'activité du système et des programmes
qui s'y exécutent jusqu'à ce que le temps imparti soit écoulé, après quoi il affiche un rapport d'analyse comme on le voit ici
avec Word Me Up XXL. Le rapport est légèrement simplifié ici pour ne pas être trop long :
count = 0029, percent = 01, name = LIBS:ft2.library
Offset = 0x00052974, Count = 0029, Function = <NOT FOUND>
count = 2019, percent = 84, name = Kickstart/kernel
Offset = 0x00011e18, Count = 0026, Function = <NOT FOUND>
Offset = 0x0000cf68, Count = 1969, Function = HAL_TaskPostTerm
Offset = 0x00025ec0, Count = 0005, Function = Internal_MemCpy
Offset = 0x0001bfbc, Count = 0005, Function = _impl_FindTask
[couic !]
Offset = 0x000274c4, Count = 0001, Function = _impl_CacheClearE
Offset = 0x00042b60, Count = 0001, Function = _FindTagItem
count = 0012, percent = 00, name = Kickstart/timer.device.kmod
Offset = 0x000019d8, Count = 0012, Function = <NOT FOUND>
count = 0186, percent = 07, name = Kickstart/rtg.library
Offset = 0x00062430, Count = 0186, Function = <NOT FOUND>
count = 0007, percent = 00, name = CLASSES:datatypes/png.datatype
Offset = 0x00006b58, Count = 0007, Function = <NOT FOUND>
count = 0008, percent = 00, name = CLASSES:datatypes/picture.datatype
Offset = 0x00003ee4, Count = 0008, Function = <NOT FOUND>
count = 0008, percent = 00, name = Kickstart/graphics.library.kmod
Offset = 0x00012a28, Count = 0008, Function = <NOT FOUND>
count = 0004, percent = 00, name = WordMeUpXXL
Offset = 0x00005d24, Count = 0004, Function = <NOT FOUND>
count = 0022, percent = 00, name = LIBS:xadmaster.library
Offset = 0x0003ae1c, Count = 0022, Function = <NOT FOUND>
count = 0028, percent = 01, name = CLASSES:datatypes/aiff.datatype
Offset = 0x000011b0, Count = 0028, Function = <NOT FOUND>
count = 0013, percent = 00, name = LIBS:Picasso96API.library
Offset = 0x00000e14, Count = 0013, Function = <NOT FOUND>
count = 0056, percent = 02, name = Kickstart/ATIRadeon.chip
Offset = 0x00000750, Count = 0056, Function = <NOT FOUND>
Summarized results :
Percent | Program
1 | LIBS:ft2.library
84 | SYS:Kickstart/kernel
0 | SYS:Kickstart/timer.device.kmod
7 | SYS:Kickstart/rtg.library
0 | CLASSES:datatypes/png.datatype
0 | CLASSES:datatypes/picture.datatype
0 | SYS:Kickstart/graphics.library.kmod
0 | Games:WordMeUpXXL/WordMeUpXXL
0 | LIBS:xadmaster.library
1 | CLASSES:datatypes/aiff.datatype
0 | LIBS:Picasso96API.library
2 | SYS:Kickstart/ATIRadeon.chip
|
Qu'est-ce qu'on peut en dire ? On constate que 84% du temps est passé dans le noyau mais toujours dans la même fonction. Ça ne
veut pas dire que le système consomme toutes les ressources, on est ici en présence de la fonction IDLE, elle attend qu'un
programme nécessite du temps d'exécution pour le scheduler. Word Me Up XXL n'est donc pas gourmand : lui et ses dépendances
consomment 16% du temps processeur, dont la moitié dans la "rtg.library".
Dans le cas de DOSBox, l'essentiel du temps est passé dans la fonction qui décode les instructions à émuler, les résultats
sont similaires à ce que donne oprofile sous Linux PPC. Pour OWB, on revient à un cas semblable à Word Me Up XXL, à savoir 17%
d'utilisation du processeur dont 7% dans le programme lui-même et 6% dans la "rtg.library".
ScummVM vu par Hieronymus
Giana Sisters vu par Hieronymus
Un bonus pour la route
Une autre fonctionnalité a été ajoutée dans le but d'étudier la performance d'un programme, où plutôt l'impact sur les caches du
processeur. En effet, depuis plusieurs années, les processeurs intègrent des aides au diagnostic concernant des dizaines ou des
centaines d'événements qui se passent dans le processeur et sont regroupés sous l'appellation "performance monitor". Comme cela
touche à des points très précis et compliqués, je ne parlerais que du type d'événements utilisés ici : les fautes de caches ou
"cache misses" en anglais.
Quand un accès mémoire est effectué, le processeur regarde en premier si la donnée est présente en cache de niveau 1. Si elle l'est,
c'est tant mieux (il s'agit d'un "cache hit" en L1), l'opération est rapide, sinon, la recherche est faite dans le cache de niveau 2.
Là, encore, si la donnée ne s'y trouve pas (on parle de "cache miss" en L2), on y accède en mémoire centrale, ce qui est lent et
fait la raison d'être des caches.
Quand l'accès concerne la lecture d'une instruction qui va être exécutée, on touche au cache d'instructions, sinon cela concerne
le cache de données. Durant la durée du profilage, Hieronymus va utiliser les événements de "cache miss" sur les caches L1 et L2
pour les instructions et les données, afin d'afficher à la fin le nombre de ces événements :
Report of cache misses :
L1 inst cache misses : 4110166
L2 inst cache misses : 202610
L1 data cache misses : 10298347
L2 data cache misses : 775383
|
Ces informations sont beaucoup moins pratiques à utiliser que le reste du rapport de profilage mais comme ces informations sont
disponibles sur les processeurs PowerPC G3 et G4, pourquoi ne pas en profiter ? Si deux versions d'un programme donnent des
résultats très différents alors les modifications effectuées ont un impact visible sur les caches, dont l'utilisation influe
directement sur les performances. A noter pour information que le PPC440 est dépourvu de performance monitor ainsi que de cache
de niveau 2.
L'inspecteur mène l'enquête
Pour terminer cet article, tout d'abord un mot sur le nom, Hieronymus. En cherchant un nom, j'ai pensé à la fonction de ce logiciel
et cela m'a évoqué un inspecteur des programmes. Ça a fait tilt : étant un grand fan des romans policier de Michael Connelly et de
son personnage principal, j'ai immédiatement pensé à ce dernier qui n'est autre que Harry Bosch, dont le vrai prénom est Hieronymus.
On apprend dans un des livres que sa mère lui a donné ce prénom par attrait pour le tourmenté peintre néerlandais du XVe et XVIe
siècle, Hieronymus van Aken, dit Jérôme Bosch.
En cette année 2010, l'inspecteur prend du grade puisque Hieronymus a été intégré dans la mise à jour du
SDK d'AmigaOS 4 ! Il se trouve plus exactement dans SDK:Local/C/Hieronymus.
L'idée de ce développement m'est venue en utilisant oprofile sur Linux pour le portage et l'optimisation de DOSBox 0.73. Et puis
dans mon travail, je m'occupe de tests, de tests de performance et de profilage...
Attention, krash en vue ! Bien que Hieronymus ait été intégré dans le SDK, un bogue dans le système fait planter l'application ou
même le système sur Sam et Pegasos. Le bogue a été isolé et remonté aux développeurs du système d'exploitation. Espérons qu'il soit corrigé
dans la prochaine mise à jour.
Cet outil devrait être très utile à tous ceux qui programment des applications gourmandes et ont à coeur d'optimiser pour le
confort des configurations les plus modestes, comme on le fait depuis 25 ans sur Amiga !
|