Test de charge : Quel outil open source pour générer une forte charge ?
Les méthodes de conception, d’implémentation, et de déploiement des applications évoluent et ces évolutions touchent également nos outils de tests. Les solutions de tests de performances sont de plus en plus nombreuses et il peut être difficile de choisir la solution qui s’ajustera aux besoins d’une organisation. En réalité, le nombre de critères à prendre en compte dans le choix d’un outil de test de performance est aussi grand que le nombre d’organisation.
Parmi les critères à prendre en compte pour choisir un outil, on peut citer :
- Le prix des licences
- Le langage permettant d’implémenter les scripts de génération de charge : il est plus facile d’utiliser un outil dont on connaît le langage.
- La facilité de création des scripts
- Le nombre de métriques remontées
- La qualité des rapports
- La communauté et la qualité de la documentation
- La capacité de l’outil à générer de la charge
Dans cet article nous nous intéresserons au dernier point et comparerons trois outils Open Source :
- Gatling : Solution implémentée en Scala avec le Framework Akka. Akka est une implémentation du design pattern Acteur qui permet une bonne gestion de la concurrence. Les scripts sont implémentés en Scala également.
- Locust : Solution implémentée en Python et qui permet également d’écrire ses scripts en Python.
- K6 : Solution implémentée en Go et qui est relativement jeune comparée aux deux autres. A l’heure où j’écris cet article, la dernière release est la 0.31.1.
Notons que Gatling et K6 proposent des services payants contrairement à Locust.
Protocole de test
Pour tester la capacité de K6, Gatling et Locust à générer de la charge, nous utiliserons le protocole suivant :
- Nous implémentons un script simple (et équivalent) pour chacune des solutions.
- Nous exécutons ces scripts sur la même machine.
- Nous comparons le débit de requêtes et les ressources physiques utilisées, pour le même nombre utilisateurs virtuels (VU).
Ce test est très simple et ne prend pas en compte :
- Les scénarios complexes et la performance des extractions et autres calculs internes. Le but est de générer le maximum de charge avec une machine unique.
- Les différentes optimisations possibles sur les outils : réglages JVM, optimisation de la machine.
Installation
Pour ce test nous utilisons une machine virtuelle :
- Virtualbox
- Fedora 33 (64 bits)
- RAM : 3072Mb
- Core CPU : 1
Nous installons également :
- Openjdk 11
- Python 3.7
- Go 1.13
L’installation de Gatling n’est pas modifiée car en consultant le script gatling.sh on observe que la JVM a déjà des configurations spécifiques (Garbage collector, Heap Size, désactivation du biased locking etc..)
Scripts
Les tests exécutent les scripts suivants :
Notons quand même plusieurs choses :
- Le script Gatling doit être modifié pour générer une charge plus ou moins importante.
- Les scripts sont configurés pour faire une requête sur une page PHP simple mise à disposition par k6.
Exécution des tests
Nous commençons avec une charge de 10 VU :
Pour cette première itération on observe que K6 et Locust génèrent bien plus de charge que Gatling. J’ai trouvé les résultats étonnants de par l’architecture de Gatling et j’ai donc fait un second tir en dupliquant 5 fois la requête dans le même script ce qui permet de générer bien plus de charge. La préparation de l’itération doit donc être très coûteuse pour cette solution. Pour les prochains tirs, nous utiliserons le script non optimisé comme pour les deux autres solutions. A 50 VU, on observe que K6 génère bien plus de charge que ses deux concurrents.
Faisons deux tirs supplémentaires à 200 et 500 VU :
On observe plusieurs choses :
- K6 génère une charge bien supérieure aux deux autres solutions. Cela peut s’expliquer par le fait que l’application est développée avec le langage Go qui a d’excellentes performances.
- Pour K6, la charge entre 200 et 500 VU a très peu augmenté ce qui indique qu’on atteint une limite : cette limite peut provenir de l’application ou de l’environnement d’exécution du test.
- Pour Locust et Gatling : entre 200 et 500 VU, le débit de requête a baissé ce qui veut dire qu’ils ont atteint leur limite et qu’ils ne peuvent pas générer plus de charge.
- Si on utilise 2 CPU, on obtient 1137 req/s avec K6, 218 req/s avec Gatling, 230 avec Locust.
Au niveau de la machine, on relève ces métriques pendant les tests à 500 VU :
On remarque que Locust consomme moins de RAM mais plus de CPU que les deux autres solutions. Étonnamment, Gatling ne consomme pas beaucoup plus de RAM que K6 bien qu’il soit exécuté sur une JVM. La consommation réseau est quant à elle proportionnelle au nombre de requêtes.
On a effectivement observé que K6 génère plus de charge que les deux autres solutions et, malgré son architecture, Gatling génère moins de charge. Comme nous l’avons vu précédemment, le scénario testé ne comporte qu’une seule requête donc si la création d’un VU est plus coûteuse avec Gatling, cela explique la différence de performance.
Conclusion
Comme dit plus haut dans cet article, il existe de multiples critères pour choisir un outil de test de charge. Nous avons fait le choix d’évaluer les solutions à partir de leur capacité à générer un grand nombre d’appels par secondes. Dans le cas où cela serait votre critère d’acceptation principal : K6 est la solution à adopter.
Et vous, quel outil open source utilisez vous pour vos tests de charges ?