Tous les processeurs SPARC intégrés aujourd'hui dans les gammes de serveurs Oracle/Fujitsu supportent une technologie nommée Chip Multithreading (CMT), similaire à l'Hyper-Threading des processeurs Intel. En résumé, il s'agit de faire tourner plusieurs threads sur un même core physique pour ne pas gâcher du temps CPU disponible, mais en utilisant plusieurs jeux de registres pour éviter des changements de contextes coûteux. Du point de vue de l'OS, on voit des processeurs virtuels (baptisés hardware threads), qui sont traités exactement comme des processeurs normaux.

Ces évolutions technologiques induisent des changements dans la façon dont on observe les performances CPU de nos serveurs. En particulier, les outils traditionnels comme vmstat ou top (basés sur les kstats) ne représentent plus la capacité de calcul brute des processeurs, mais plutôt la disponibilité des processeurs virtuels. On a en fait une décorrélation partielle de la disponibilité de ces processeurs virtuels et de la capacité du core à exécuter des instructions. En d'autres termes, on peut voir de la puissance CPU disponible avec vmstat alors que le core est déjà saturé.

Il nous faut donc un nouvel outil pour mesurer la charge des cores, et nous avons de la chance, puisque cet outil existe, il s'agit de corestat.

Voilà quelques points notables sur l'outil :

  • il ne fait pas partie de la distribution Solaris standard, c'est un script perl téléchargeable sur le site cooltools
  • il s'appuie sur la commande système cpustat pour interroger les PIC (Performance Instrumentation Counter) des processeurs virtuels et les agréger par core
  • corollaire, il y a une version du script par famille de processeurs, les évènements supportés par les PIC différant selon les processeurs
  • il se lance en tant que root.

Exemple d'utilisation

Voici une petite illustration des écarts que l'on peut observer entre vmstat et corestat, sur un serveur doté de 8 cores SPARC64 VII, et donc 16 processeurs virtuels.

# psrinfo -pv The physical processor has 8 virtual processors (0-7) SPARC64-VII (portid 1024 impl 0x7 ver 0x91 clock 2400 MHz) The physical processor has 8 virtual processors (40-47) SPARC64-VII (portid 1064 impl 0x7 ver 0x91 clock 2400 MHz)
On lance 8 threads qui occuperont autant de temps CPU qu'ils peuvent :
$ perl -e 'while (--$ARGV[0] and fork) {}; while () {}' 8

Immédiatement, vmstat affiche une charge CPU de l'ordre de 50%, correspondant au fait que 8 des 16 processeurs virtuels sont sollicités en permanence (le serveur ne fait rien d'autre de particulier en dehors de ça) :

$ vmstat 1 kthr memory page disk faults cpu r b w swap free re mf pi po fr de sr rm s0 s1 s2 in sy cs us sy id [...] 0 0 0 120698872 59208352 1 3 0 0 0 0 0 0 4 4 0 811 812 308 50 0 50 0 0 0 120698872 59208352 2 4 0 0 0 0 0 0 3 3 0 565 1161 321 50 0 50 0 0 0 120698872 59208352 4 6 0 0 0 0 0 0 0 0 0 691 3185 534 50 0 49 0 0 0 120698872 59208352 0 2 0 0 0 0 0 0 0 0 0 802 1089 297 50 0 49

Dans le même temps, corestat affiche une activité plutôt de l'ordre de 80% :

# corestat -i 10 CPU Utilization Fri Oct 29 11:17:53 2010 CPU (Thd) %Usr+Sys --------------------- ----------- 0 (0,1) 92.55 1 (2,3) 93.19 2 (4,5) 84.71 3 (6,7) 56.94 20 (40,41) 89.32 21 (42,43) 92.12 22 (44,45) 80.95 23 (46,47) 60.93 Avg 81.34 CPU Utilization Fri Oct 29 11:18:03 2010 CPU (Thd) %Usr+Sys --------------------- ----------- 0 (0,1) 95.00 1 (2,3) 84.88 2 (4,5) 76.17 3 (6,7) 71.74 20 (40,41) 91.16 21 (42,43) 84.44 22 (44,45) 85.05 23 (46,47) 85.03 Avg 84.19

Intuitivement, le résultat se comprend bien : dès lors que l'un des deux threads hardwares tournant sur un core donné est très consommateur en temps de calcul, il reste peu de marge pour l'autre.

Il nous faut donc désormais ajouter systématiquement l'analyse de la charge des cores à notre panoplie d'outils d'observation des performances. Accessoirement, on retrouve les mêmes problématiques avec l'Hyper-Threading d'Intel, que ce soit sous Solaris ou sous Linux (pour le cas de Linux, je n'ai pas encore cherché de solutions pour contourner le problème, mais ça viendra).