Limiter la bande passante d'une VM pour tester des commandes BPF
En lisant le livre BPF Performance Tools de Brendan Gregg, j’ai eu envie de tester les nouveaux outils disponibles.
En particulier, j’ai voulu voir si des problèmes de saturation disque pouvaient être détectés avec biosnoop
, biotop
, biolatency
et/ou bitesize
.
Dans cet article, on verra comment configurer une VM VirtualBox pour essayer ces outils.
Le protocole de test
Le protocole de test sera très simple.
Il s’agira du lancement d’une application web Java tout ce qu’il y a de plus standard (Spring PetClinic).
Avant le lancement de l’application, une commande bio*
sera exécutée pour le surveiller.
Le protocole de test sera joué deux fois. Une fois sur une machine non bridée. Une fois sur une machine pour laquelle la bande passante du disque est limitée à 1 Mo/s.
Le setup
En utilisant l’outil VBoxManage
de VirtualBox, il est possible d’accéder à beaucoup plus de paramètres que ceux disponibles dans l’interface graphique.
Ici, on va s’intéresser plus particulièrement aux commandes VBoxManage storageattach
et VBoxManage bandwidthctl
.
Avec bandwidthctl
, on va créer une limite à la bande passante disque utilisable par une VM.
Avec storageattach
, on va associer le disque dur d’une VM à la limite précédemment créée.
Les deux commandes listées ci-dessous doivent être exécutées quand la VM est éteinte. |
Je dispose d’une VM nommée Archlinux
.
Elle a un unique disque dur sur lequel tous les fichiers sont stockés (OS, /home
et /boot
, restons simples).
Tout d’abord, il faut créer une limite.
On la dimensionnera très largement pour être sur qu’elle ne ralentit pas le démarrage de la VM.
Car oui, j’ai essayé avec une valeur de base à 1 Ko/s, Grub a mis plusieurs minutes pour pouvoir charger ses propres fichiers.
VBoxManage bandwidthctl Archlinux add "Disk bandwidth limit" --type disk --limit 1000M
Ensuite, il faut associer le disque dur de la VM à cette limite.
VBoxManage storageattach Archlinux --storagectl "SATA" --port 0 --bandwidthgroup "Disk bandwidth limit"
Pour démarrer l’application, un simple java -jar target/*.jar
suffira.
Entre deux redémarrages, il sera nécessaire de vider le cache Linux avec echo 3 | sudo tee /proc/sys/vm/drop_caches
.
On pourra également vérifier que le jar principal n’est pas en cache avec la commande vmtouch
.
Test sans limitation
Avant de lancer l’application, on vérifie que le jar de petclinic n’est pas en cache.
[alarm@archlinux ~]$ vmtouch -v ./spring-petclinic/target/*.jar
./spring-petclinic/target/spring-petclinic-2.2.0.BUILD-SNAPSHOT.jar
[ ] 0/11643
Files: 1
Directories: 0
Resident Pages: 0/11643 0/45M 0%
Elapsed: 0.000353 seconds
Lorsque l’application est lancée, on peut voir que le processus java
charge plusieurs dizaines de Mo depuis le disque.
Cela correspond non seulement à l’uberjar mais également à tous les fichiers dont la JVM a besoin, y compris le fichier rt.jar
.
Ces I/O sont réalisées avec une latence excellente (<1 ms en moyenne).
[alarm@archlinux ~]$ sudo biotop -C -r 10
Tracing... Output every 1 secs. Hit Ctrl-C to end
[...]
22:44:29 loadavg: 0.22 0.35 0.35 4/159 4093
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
4076 java R 8 0 sda 497 31376.0 0.49
4076 C2 CompilerThre R 8 0 sda 22 1632.0 0.59
4076 bash R 8 0 sda 14 696.0 0.39
4076 C1 CompilerThre R 8 0 sda 6 348.0 0.44
509 bash R 8 0 sda 3 140.0 2.28
22:44:30 loadavg: 0.37 0.38 0.36 4/163 4097
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
4076 java R 8 0 sda 640 8792.0 0.48
4076 background-prei R 8 0 sda 165 2044.0 0.51
4076 C2 CompilerThre R 8 0 sda 1 124.0 0.57
22:44:31 loadavg: 0.37 0.38 0.36 4/162 4098
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
4076 java R 8 0 sda 391 4100.0 0.52
4076 background-prei R 8 0 sda 254 3908.0 0.49
4076 Thread-0 R 8 0 sda 37 316.0 0.45
22:44:32 loadavg: 0.37 0.38 0.36 4/162 4098
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
4076 java R 8 0 sda 313 3480.0 0.59
Une fois l’application stoppée, on peut constater que le jar est bien dans le FS cache.
On peut donc au choix utiliser vmtouch -e
ou bien echo 3 | sudo tee /proc/sys/vm/drop_caches
pour l’en supprimer.
Puisqu’on veut avoir le plus d’I/O possible, je choisis de vider entièrement le cache.
[alarm@archlinux ~]$ vmtouch -v ./spring-petclinic/target/*.jar
./spring-petclinic/target/spring-petclinic-2.2.0.BUILD-SNAPSHOT.jar
[ooooOooOooooOoOoOOOOOOooooOooOOooooooooOooooooooooOooooooOoO] 8777/11643
Files: 1
Directories: 0
Resident Pages: 8777/11643 34M/45M 75.4%
Elapsed: 0.000901 seconds
Test avec limitation
Cette fois, je choisis de limiter la bande passante disque à 1 Mo/s. J’ai essayé avec des valeurs plus faibles mais cela figeait parfois la VM. Il semble que le bruit de fond soit suffisant pour parfois atteindre cette limite. Quoi qu’il en soit, 1 Mo/s est une bonne limite sachant que le jar de PetClinic fait 45 Mo.
J’exécute donc la commande ci-dessous.
VBoxManage bandwidthctl Archlinux set "Disk bandwidth limit" --limit 1M
Cette fois, le résultat est bien différent. Je constate déjà un temps de chargement beaucoup plus long de l’application. Sans l’avoir formellement mesuré, je peux déjà affirmer que la limitation de bande passante fonctionne bien.
Mais c’est surtout la sortie de biotop
qui est révélatrice.
On voit bien que le processus java
ne peut pas lire les données plus rapidement que 1 Mo/s.
Mais en plus, on constate que pour lire ce Mo, la latence moyenne est située entre 50 et 100ms.
Soit entre 50x et 100x plus que comparé au premier run.
On voit donc comment détecter une saturation disque avec biotop
.
[alarm@archlinux ~]$ sudo biotop -C -r 10
Tracing... Output every 1 secs. Hit Ctrl-C to end
[...]
22:32:14 loadavg: 0.49 0.43 0.27 2/138 3933
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
3932 java R 8 0 sda 9 1060.0 110.47
22:32:15 loadavg: 0.49 0.43 0.27 2/138 3933
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
3932 java R 8 0 sda 17 1020.0 59.48
22:32:16 loadavg: 0.49 0.43 0.27 7/138 3933
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
3932 java R 8 0 sda 11 996.0 90.63
22:32:17 loadavg: 0.49 0.43 0.27 6/143 3938
PID COMM D MAJ MIN DISK I/O Kbytes AVGms
3932 java R 8 0 sda 16 980.0 62.48
Quelques surprises
J’avais initialement prévu de tester trois autres commandes. Mais cela n’a pas été possible.
La commande biosnoop
liste chaque ouverture de fichier.
Au chargement d’une JVM, cela représente bien trop de bruit pour être utilisable.
La commande bitesize
indique la taille des I/O demandées par l’application.
Elle ne prend pas en compte la bande passante effectivement disponible pour ces I/O.
Elle s’adresse dont à une autre problématique.
Pour finir, la commande biolatency
était intéressante mais elle met l’accent sur la latence disque, comme son nom l’indique.
Dans le listing précédent, on voit que la latence est plus élevée.
Mais s’agissant d’un problème de bande passante avant tout, je pense que biotop
est plus adapté.
Pour aller plus loin
La commande VBoxManage bandwidthctl
peut également être appliquée sur une carte réseau.
Ce sera l’occasion de tester d’autres nouveaux outils comme soconnect
et détecter des congestions.
Le livre BPF Performance Tools regorge de nouveaux outils. Je suis curieux de voir comment des cas d’étude peuvent être créés en totale isolation pour expérimenter chacun de ces outils.
Si vous avez des questions ou voulez me faire part de vos commentaires, envoyez moi un tweet (@pingtimeout). Et si vous avez apprécié cet article et voulez soutenir mon travail, vous pouvez toujours m’offrir un café sur BuyMeACoffee ☕️.