Artisan Numérique

/développement/java/nailgun/ Accélérer le démarrage du compilateur Closure avec NailGun

Contrairement aux idées reçues, une fois lancée, une application Java se comporte aussi bien qu'une autre en python, dotNet ou autre langage managé. Le gros problème n'est donc pas plus la rapidité de la VM que le temps nécessaire à sa mise en route. Sur une bonne machine, un outil comme Google Closure Compiler prend ainsi 3 secondes à chaque instance, et ce n'est clairement pas le temps qu'il faut pour compiler 100 lignes de JS ;-)

Heureusement il existe une solution rapide à mettre en oeuvre et très efficace : NailGun.

Les lenteurs du démarrage

Java est lent au lancement, c'est un fait tenace que les versions successives de la JVM ne font qu'atténuer. Et je suis bien en peine de le reconnaître mais la CLR (.net), sur ce point, a toujours été diablement plus efficace.

Les raisons de cette lenteur serait un peu longues à énumérer. Disons pour simplifier que coller des classes signées dans des fichiers zip implique, au démarrage de la VM, un ouverture, décompression, passage en revue de toutes les classes de tous les jars qui sont dans le CLASSPATH. Au regard de la taille du JDK, ce n'est finalement pas si lent que cela ;-)

D'un autre côté ce problème n'en est pas réellement un dans le cadre d'usage standard de Java : pour des services lancés sur du long terme. En revanche, s'agissant d'une commande simple, c'est une tout autre histoire.

Une bonne manière serait donc de ne pas avoir à effectuer ce travail à chaque lancement d'une commande. Et c'est exactement ce que réalise NailGun (littéralement "pistolet à clou") depuis prés de... pfff... Huit ans :)

Un serveur JVM

NailGun se compose d'une partie "serveur", écrite en Java, et un client en C. Le principe est finalement simple, le serveur étant écrit en Java induit à son lancement le chargement d'une instance de la JVM et bootstraping du JDK.

Le client n'a plus qu'à lui expédier, via TCP/IP, des noms de classes à exécuter. Le serveur lui renverra en retour les écritures faites par la classe dans sa sortie standard. Et le tour est joué.

Installation

Sur Debian c'est assez simple à installer. Un sudo apt-get install nailgun suffit . En revanche cela ne marchera pas car les mainteneurs ont eu la mauvaise idée de renommer le client ng-nailgun au lieu de ng. Et croyez moi, il n'aime pas cela du tout. Fort heureusement, la correction est assez simple :

gastonsudo ln -s /usr/bin/ng-nailgun /usr/bin/ng

Lancement du serveur

Pas de chichi ni de script d'init pour NailGun (même si c'est assez simple à réaliser). Un simple lancement à la mano en tâche de fond ferra l'affaire. La seule chose à bien faire avant est de définir un CLASSPATH comprenant le JAR de NailGun et celui des applications qui souhaitent en bénéficier. Ici il s'agit du compilateur Closure qui se trouve dans le dossier $PWD/libs

gastonexport CLASSPATH=$PWD/libs/compiler.jar:/usr/share/java/nailgun.jar
gastonjava com.martiansoftware.nailgun.NGServer &
NGServer started on all interfaces, port 2113

Voilà, ça roule, le serveur est en activité sur le port 2113.

Test du client

Pour voir un peu ce que cela donne, voyons une compilation Closure sans NailGun

gastontime java -jar libs/compiler.jar --js sources/server/server.js --js_output_file bin/server/server.js
5,00s user 0,08s system 216% cpu 2,341 total

Ok, donc 2.3 secondes pour 100 lignes de code. Voyons maintenant avec NailGun

gastontime ng com.google.javascript.jscomp.CommandLineRunner --js sources/server/server.js  --js_output_file bin/server/server.js
0,00s user 0,00s system 0% cpu 0,185 total

Et hop, on tombe à 185ms, ce qui change un peu tout vous en conviendrez.

Conclusion

Lorsque j'avais écris la première version de cet article, il y a tout juste 7 ans (!!!) je concluais par "Nailgun est une rustine pratique mais je l'espère bientôt obsolète. Le temps de chargement de Java doit pouvoir être encore à améliorer, ne serait-ce qu'en débridant le vérifieur de classes qui consomme beaucoup de ressources au démarrage."

En bien 7 ans plus tard j'en suis pour mes frais et NailGun, lui, est toujours d'actualité...