Tests approfondis de G-WAN

Il y a quelques jours, j’ai découvert G-WAN, un nouveau serveur web « révolutionnaire » d’après son auteur. Ce dernier annonce des performances assez hallucinantes, même face à Apache, NginX ou Lighttpd qui sont les serveurs web les plus connus.

Ce qui m’a vraiment étonné, c’est la différence de performance annoncée :

G-WAN benchmarkJ’estime maîtriser assez bien Apache ou NginX, et je m’étonne évidemment de telles différences de performances. J’ai donc décidé d’enquêter !

On commence par un rapide tour du logiciel : celui-ci peut se télécharger gratuitement sur le site officiel, mais surprise, le code source n’est pas ouvert ! Vous téléchargerez donc uniquement un binaire (deux versions : 32 bits et 64 bits). Cela serait normalement un argument de trop pour moi pour de la prod, mais comme je suis là pour enquêter (et pas pour utiliser ce logiciel en production), je fais confiance et je télécharge.

Je lance alors un rapide benchmark et je suis effectivement impressionné par la vitesse d’exécution  que ce soit sur du statique (appeler une image), ou bien plus surprenant  un script PHP ! Je retrouve à peu près les performances annoncées sur le site officiel. Il s’agit donc de savoir quelle est la recette miracle. Soit les développeurs sont des Dieux, soit il y a baleine sous gravier 🙂

En lisant la (faible) documentation de G-Wan, j’apprends que PHP est en plus lancé de la pire des façons : comme un CGI classique. Autant dire que face à un Apache bien configuré (avec FastCGI par exemple), il n’y a normalement pas photo. Et là l’outil se permet de faire 50.000 requêtes par seconde, là où Apache et NginX plafonnent à 5.000 environ (le script est un simple ‘echo « hello world »‘). Comment ?

Tests PHP

Comme c’est la partie qui me surprend le plus, je me suis d’abord penché sur la partie PHP. J’ai donc créé un script un tout petit peu plus compliqué :

<?php
$m = new memcache();
$r = $m->connect('127.0.0.1');
if (!$r) exit(500);
$z =$r->increment('counter');
if ($z === false) {
  $r->set('counter', 0);
} 
exit(200);

Le script reste assez lisible : il se connecte à Memcache et incrémente une variable ‘counter’ de un. Si elle n’existe pas, on la créé avec la valeur 0.

Le support de PHP est un peu limité dans G-Wan, mais je vais passer outre :

  • il faut absolument que le script se termine avec un exit(CODE_HTTP) ou sinon la page met des dizaines de secondes à charger (G-Wan doit sûrement attendre quelque chose qui n’arrive pas).
  • il ne gère (pour le moment) les attributs GET que dans $argv (à vous de reconstruire $_GET). Pour ce point c’est « logique » vu que le logiciel utilise php-cli
  • et donc pour la même raison qu’au dessus, il ne gère pas non plus les cookies (qui sont un header envoyé lorsque votre navigateur demande la page).

Comme il s’agit d’un ajout récent nous serons indulgent sur cette partie (l’auteur a fait un appel à contribution pour améliorer le support de PHP).

Mais bref, voilà mon script qui fonctionne. Petit benchmark simple : j’appelle mon script PHP 50 fois, et je regarde la valeur de ‘counter’ dans Memcache. Et là, GROSSE surprise : le compteur vaut « 1 ». Et pourtant le testeur que j’utilise (weighttp) me dit bien que 100% des requêtes ont réussies. Mon petit doigt me dit que G-Wan n’a exécuté le script qu’une seule fois, et s’est cru permis de me retourner du cache pour les autres appels … Pas très ‘fair’ tout ça ! Mais on va vérifier nos dires avec ce 2e script :

<?php
echo rand(0,1000)."\n";
exit(200);

Relativement simple n’est-ce pas ? Juste afficher un nombre aléatoire. Cette fois je fais une simple boucle shell avec wget pour afficher la sortie du script :

for i in $(seq 1 10); do wget -q -O - 'http://127.0.0.1:8080/?test.php' ; done
379
379
379
379
379
379
379
379
379
379

Et le créateur de G-Wan hurle à qui veut l’entendre qu’il ne fait pas de caching … A d’autres (ou alors j’ai pas compris ce qu’il disait).

MAJ 17/01/2013 – Je faisais référence à ce post de Pierre mais en relisant j’ai mal interprété son propos : Oui GWAN fait du cache (la FAQ le précisait bien), mais d’après lui cela ne doit pas expliquer seul les différences de performances.

D’après mes tests, cette mise en cache dure une seconde 200ms comme annoncé dans la documentation et dépend uniquement de l’URL appelée ! Donc si vous appelez votre script depuis 10 IPs différentes (et/ou avec 10 valeurs de cookies différentes), vous aurez le même cache renvoyé. Imaginez la catastrophe sur un site E-Commerce. L’implémentation de PHP dans G-Wan est certes incomplète, mais dans ce cas ne venez pas me voir avec un benchmark qui compare deux choses très différentes.

Tests sur les fichiers statiques

Les performances pour servir des statiques sont également excellentes. J’ai voulu vérifier si là aussi il y avait un cache. Ma méthode simple : un premier shell écrit régulièrement dans un fichier:

while sleep 0.01; do echo $RANDOM > test.html ; done

Et dans l’autre shell, je récupère ce fichier 10 fois de suite :

for i in $(seq 1 10); do wget -q -O - 'http://127.0.0.1:8080/test.html' ; done
29252
29252
29252
29252
29252
29252
29252
29252
29252
29252

Bingo, là encore, du cache ! Et aucune variation également sur la valeur du cookie, l’IP du visiteur, etc. Donc effectivement, si le serveur n’a plus besoin d’aller relire le fichier à chaque fois, les performances seront forcément meilleures 😉
Au passage, les headers renvoyés par le serveur sont curieux :

$ wget --server-response -O - http://127.0.0.1:8080/test.html
[...]
Last-Modified: Thu, 01 Jan 1970 00:06:16 GMT
[...]

$ stat 0.0.0.0_8080/#0.0.0.0/www/test.html
[...]
Access: 2013-01-17 14:21:21.824193231 +0100
Modify: 2013-01-12 14:23:38.376769655 +0100
Change: 2013-01-12 14:23:38.376769655 +0100

Alors qu’on attend plutôt la date effective de modification de ce fichier statique. Probablement un bug ?

 

Conclusion (partielle)

Jusque là, j’ai juste montré que comparer les performances de base de G-Wan, en statique ou avec du PHP n’était pas fair play car ce logiciel est fortement basé sur du cache. Maintenant, imaginez que ce comportement vous aille (on peut honnêtement se demander si on a vraiment besoin d’aller relire un fichier plat à chaque fois). Les performances de G-Wan restent très élevées quand même ! Par contre pour du PHP, oubliez tout de suite vu l’implémentation actuelle ! Si on pouvait choisir sur quels arguments baser le cache (par exemple IP+headers) pourquoi pas, mais là c’est juste inutilisable. On attendra donc une implémentation plus complète de cette partie. Et nulle part dans la documentation je n’ai trouvé comment désactiver ce cache ou changer les arguments (pas juste URL).
Dans un prochain article, je partirais donc du postulat qu’une seconde de cache me convient, et je regarderai alors les performances et essayerai de les expliquer.

5 réflexions au sujet de « Tests approfondis de G-WAN »

  1. Interesting findings. I wonder how long before G-Wan author will appear here to defend its « approach » to PHP execution. I also wonder how many other corners does it cut in the handling of common HTTP requests. It must be one of the reasons it’s closed source.

  2. A G-WAN fan boy already replied to this article, but I trashed his comment because of bad behaviour (I don’t have a blog to be insulted, nor to have my professionalism questioned).

  3. « il faut absolument que le script se termine avec un exit(CODE_HTTP) ou sinon la page met des dizaines de secondes à charger (G-Wan doit sûrement attendre quelque chose qui n’arrive pas). »

    En fait, c’est le navigateur qui bloque, pas G-Wan.

    Cela vient du protocole HTTP: sans entête « content-lenght » le navigateur Web ne peut pas savoir quand la réponse est terminée. Il attend donc environ 20 secondes pour voir si plus de données arrivent (et si, rien ne vient, il affiche ce qu’il a reçu).

    Le code de retour des scripts de G-Wan est le statut du protocole HTTP, et il sert à générer automatiquement les entêtes HTTP. Si vous omettez ce code de retour, vous devez créer vous-même ces entêtes pour dire au navigateur Web quelle est la longueur de la réponse (ou vous devez parler à un client Javascript qui va lire la réponse sans tenir compte des entêtes manquants).

    Les exemples de servlet donnés avec G-Wan expliquent ce mécanisme en détail.

  4. Bonjour,

    Article tres interessant, il y en a tellement peu 🙁

    A un moment vous dites que « Donc si vous appelez votre script depuis 10 IPs différentes (et/ou avec 10 valeurs de cookies différentes), vous aurez le même cache renvoyé. Imaginez la catastrophe sur un site E-Commerce.  »
    je suis pas sure de comprendre, le porbleme avec un site de e-commerce ? pouvez vous expliquer ?

    Je voulais aussi savoir si vous aviez poussé un peu plus votre investigation ?
    G-Wan semble interressant dans le sens que je pourrai utilisé du c compilé, mais est ce vraiment performant. j’ai du mal à faire confiance au site de g-Wan, car dans les graph de perf les autres sont présentés comme étant à la ramasse et on retrouve tellement de commentaire sur les forum au sujet de G-Wan qui ont viré à l’enguelade (intervention de l’auteur de G-Wan entre autre sous différents pseudo), que finalement trouver des élements objectifs semblent impossible.

    Et sinon dans le meme genre connaissez vous des systemes de genération de page web avec des langages compilé tels que C ou C++ et qui seraient performants ?

    Merci.

  5. Bonjour,
    Imaginez 10 visiteurs avec un panier différent qui visitent la page d’accueil de votre site : le premier visiteur a un élément dans son panier, donc sur son écran il va probablement avoir une icone avec « 1 achat ».

    Les 9 visiteurs suivants verront exactement la même page avec écrit « 1 achat ». Ils peuvent aussi se retrouver avec un texte du style « Bonjour M. Dupont ! », alors que c’est juste le nom du premier visiteur …

    Et c’est pire pour le listing du panier.

    Mais ça c’est sur du PHP. Sur du C/C++ je ne sais pas le comportement de G-Wan. Toutefois, une application complète E-Commerce écrite en C/C++, c’est plutôt très rare, et en général peu de problème de performance avec un tel langage. Si le code est bien fait et gère les threads, les concurrents NginX ou Apache pourront très bien faire le boulot.

Laisser un commentaire

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