Réduire la consommation CPU d’une machine virtuelle sous VMWare

Une des idées de la virtualisation est de concentrer sur un serveur physique plusieurs serveur virtualisés qui utilisent peu de ressources. Toutefois même quand une machine « ne fait rien » elle consomme quand même un peu de CPU pour assurer le fonctionnement de son noyau. Ce niveau plancher de consommation CPU peut parfois s’avérer élevé et on s’aperçoit vite qu’il limite fortement le nombre de machines virtuelles que l’on peut faire tourner simultanément sans perte de performances. Cet article montre comment réduire de façon significative la consommation des systèmes Linux et FreeBSD virtualisés.

Une grande partie de cette consommation CPU plancher est utilisée à traiter des interruptions de timer. Comme la machine est virtuelle, le timer est émulé et cette émulation est coûteuse. Dans le document Timekeeping in VMWare Virtual Machines diffusé par VMWare il et préconisé de réduire la fréquence de ces interruptions.

Les distributions modernes de Linux et FreeBSD ont un timer réglé à 1000Hz ce qui provoque 1000 interruptions par seconde qu’il faut traiter. Ces interruptions sont utiles pour gérer finement l’horloge système. L’avantage est que cette cadence est bien adaptée aux applications multimédia. L’inconvénient est que l’on utilise rarement des serveurs virtualisés pour y faire tourner des applications multimédia, ce n’est pas adapté. Une telle cadence est donc inutile.

L’expérience m’a montré qu’en réduisant à 100 Hz cette cadence on divisait par 4 la consommation CPU plancher. 100Hz est parfaitement adapté à une utilisation de type serveur.

Changer la fréquence du timer sur une machine Linux

Plusieurs cas peuvent se présenter :

Vous pouvez, voulez, savez recompiler le noyau :

  • Noyau linux 2.4.x : le timer n’est pas configurable, sa valeur est fixée à 100Hz. C’est plutôt bien en virtualisation.
  • Noyau linux 2.6.x : le timer peut être configuré parmi les valeurs 100, 250, 300 et 1000 Hz, c’est une constante du noyau définie avant sa compilation. 100 est recommandé pour un usage de type serveur. 250 et 300 sont recommandés pour les lecteurs vidéo PAL et NTSC respectivement. 1000 est recommandé pour un usage de type bureautique avec prise en charge multimédia. Pour changer cette constante avant recompilation du noyau, tapez make menuconfig dans le répertoire des sources de linux et allez dans la rubrique « Processor Types and features » et modifiez la valeur de « Timer Frequency »
  • Noyau linux 2.6.21+ : Il est possible à partir de cette version du noyau de paramétrer un mode « tickless » dans lequel le interruptions timer sont désactivées quand le système est au repos. Pour le positionner tapez make menuconfig dans le répertoire des sources de linux et allez dans la rubrique « Processor Types and Features » et cochez l’option « Tickless System (Dynamic Ticks) », elle est tout en haut de la liste. Ce paramètre donne de très bons résultats en virtualisation, un système au repos consommera environ 6 fois moins de CPU qu’un système au repos sans l’option tickless avec HZ=1000.

Vous ne pouvez pas, ne voulez pas ou ne savez pas recompiler le noyau :

La plupart des distributions linux qui embarquent un noyau de version 2.6.21 et plus ont l’option tickless activée. Vous n’avez rien à faire.

Le distributions CentOS et RedHat 5.4 à destination des entreprises ont un noyau 2.6.18 ne disposant pas du mode tickless. Ils sont de plus configurés pour utiliser une fréquence de timer de 1000Hz. Ils ont toutefois un patch xen qui permet de passer un diviseur en argument au noyau lors du boot. Modifiez le fichier /boot/grub/grub.conf pour ajouter l’option divider=10 à la fin des paramètres du noyau comme sur l’exemple ci dessous:

# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/VolGroup00/LogVol00
#          initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-164.11.1.el5)
     root (hd0,0)
     kernel /vmlinuz-2.6.18-164.11.1.el5 ro root=/dev/VolGroup00/LogVol00 divider=10
     initrd /initrd-2.6.18-164.11.1.el5.img

Le diviseur agira sur la fréquence. Ici le diviseur vaut 10, donc 1000 / 10 = 100HZ.

Changer la fréquence du timer sur une machine FreeBSD

Là encore la fréquence par défaut des dernières version de FreeBSD est de 1000Hz. Toutefois sur ce système la valeur est configurable dans le fichier des paramètres du lanceur du noyau. Editez le fichier /boot/loader.conf et ajoutez la ligne suivante :

kern.hz=100

Rebootez le système pour sa prise en compte.

Et les machines virtuelles Windows ?

Il n’y a pas de moyen simple de configurer la fréquence du timer de windows. Elle est variable dynamiquement dans une plage qui va de 64Hz à 2000Hz. Certains programmes le font monter à 1000Hz comme par exemple quicktime ou Microsoft SQL Server. VMWare met en garde sur l’installation de tels programmes dans une machine virtuelle. Pour connaitre la fréquence en cours sur un windows vous pouvez utiliser l’outil ClockRes qui fait partie des sysinternals de Microsoft. C’est un outil qui s’utilise en ligne de commande, il vous donnera la plage possible et la valeur courante de la période d’interruptions de timer en millisecondes.

Exemple de résultat de clockres sous windows XP SP3 virtualisé :

ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com

Maximum timer interval: 15.625 ms
Minimum timer interval: 1.000 ms
Current timer interval: 15.625 ms

En ce qui concerne SQL Server 2005 et 2008, Microsoft est conscient du problème que cela peut poser dans l’article KB972767 de sa base de connaissances. Il ne parle toutefois pas d’impact en virtualisation mais de surconsommation électrique de la machine. En réalité les deux sont liés car sur une machine physique, augmenter la fréquence des interruptions timer provoque une surconsommation électrique, le processeur étant moins souvent au repos. Sur un ordinateur portable vous divisez par 2 la tenue en charge de la batterie quand la fréquence est à 1000Hz.

Dans sont article Microsoft préconise l’installation du dernier patch cumulatif pour SQL Server. Pour ma part, le lien qui est dans l’article renvoie vers le patch cumulatif 5 pour SQL Server 2005 et j’ai constaté qu’il ne résout pas le problème. En revanche le problème est résolu dans le patch cumulatif 7 de SQL Server 2005. Je n’ai pas eu l’occasion de tester le patch pour SQL Server 2008 mais selon Microsoft le problème est le même.

Ceci s’applique aussi pour ceux d’entre-vous qui par soucis d’économie (ou pour test) ont installé leur VMWare vCenter sur une machine virtuelle. vCenter embarque un SQL Server 2005 Express Edition. Vous économiserez de la CPU en installant le patch cumulatif 7 pour SQL Server 2005.

8 réflexions sur « Réduire la consommation CPU d’une machine virtuelle sous VMWare »

    • Oui, en fait c’est valable pour toutes les versions et toutes les éditions de VMWare, ESX/ESXi mais aussi Workstation, player, etc… La gestion des interruptions timer est la bête noire de la virtualisation classique.

    • Oui, probablement. Même si j’ai peu d’expérience avec les autres solutions de virtualisation c’est tout de même l’OS virtualisé qui provoque cette charge. Il n’y a pas de raison pour que ça change d’un conteneur à un autre.

  1. Bonjour

    Est ce que cette manipulation est valable pour diminuer la charge CPU d’une VM lors de benchs tests. ( machine serveur type Wensphere )

    • Cette opération ne fait que diminuer la consommation CPU plancher de la VM quand elle est au repos. Lors d’un stress test cela ne peut pas faire de mal mais ne va pas libérer de grosses quantités de CPU pour autant.

  2. Ping : 인하대학교 로보트연구회 - 질문 답변 - 일반 tv에 dmb를 수신하려면...

Répondre à René Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *