samedi, mars 2 2013

Pool de thread avec limite de parallélisation

Je travaillais cette semaine sur un script python qui récupérait des centaines de milliers de données depuis un serveur. Pour gagner en temps de calcul, j'ai décidé de faire des threads. Limitant la taille de mes tâches parallèles à un nombre spécifique, le script bloquait... car j'utilisais des fonctions threadées qui lançaient récursivement d'autres threads. Sauf que la Queue que j'utilisais pour faire le pool se bloquait si trop de threads se lançaient en même temps attendant indéfiniment que quelqu'un veuille bien lire la Queue... J'ai alors trouvé ma solution, et je la partage avec vous. Je vous explique le problème, je vous montre un exemple, et ensuite on voit la solution.

Lire la suite...

lundi, février 18 2013

Coloriser la sortie d'un programme

Développant sur Google Appengine en ce moment, en python, j'utilise les logs à foison. Ces logs sont pratique et ont un niveau d'information (WARNING, INFO, ERROR...). Mais la lisibilité n'est pas forcément adaptée, car en effet les logs sont simplement des lignes de texte. C'est alors qu'une idée m'a frappée (sans gravité, j'ai pas eut mal): et si je colorisai la sortie. Ma méthode fonctionne pour à peu près tous les programmes que vous utilisez dans un terminal, et peut être adaptée à pas mal de situations

Lire la suite...

lundi, mai 28 2012

Go, routines et canaux - introduction au langage

Il y tellement de nouveaux langages, quand un de ceux là sort du lot c'est en général parce qu'il offre des concepts particuliers. Go est un de ceux là, et les concepts de routines, de canaux et de fonctions différées ne sont qu'une infime partie des possibilités que vous pouvez découvrir dans ce langage. Testons un peu ce langage.

Lire la suite...

lundi, mai 21 2012

Google App Engine et le souci os_compat

Google AppEngine propose est un service de développement web assez puissant et très intéressant qui permet de faire une application "scalable" en Java, Python et maintenant en Go. Le souci, si comme moi vous avez "MyPaint" et par conséquent le paquet protobuf-python... vous allez vous taper une erreur monstrueuse au démarrage de votre application... on va trouver une méthode simple pour contourner ce souci

Lire la suite...

samedi, mars 31 2012

Intégration continue - PHP, Selenium et Xvfb - Partie 1

Depuis quelques mois je me suis penché sur les outils d'intégration continue pour les projets PHP. Il en existe un bon paquet, mais celui qui pour le moment répond le mieux à mes attentes reste phpUnderControl. L'installation reste tout de même assez complexe et il me parait bon de vous montrer comment mettre en oeuvre ce genre d'outil. Le but étant de vous aider pas à pas à installer les outils qui permettront d'utiliser un service d'intégration continue. Nous allons passer en revue les outils à installer depuis PEAR, puis Selenium et enfin comment intégrer tout ça dans phpUnderControl.

Certes, je ne vais pas vous donner "la solution dans les règles de l'art" car chaque projet est différent, chaque attente est spécifique... Mais vous pourrez adapter au besoin les explications.

Nous allons donc procéder à ces opérations:

  • installer les outils pear: phpcs, phpmd, phpcpd, phpunit
  • installer selenium IDE avec le plugin php (ces outils ne sont pas obligatoires mais rendent la tâche tellement plus simple...)
  • préparer un environnement X virtuel pour lancer les tests selenium
  • installer phpundercontrol
  • configurer la bête...

Les deux derniers points seront dans la partie 2, pour le moment il faut s'assurer d'avoir tous les composants nécessaires à la bonne conduite du projet.

En ce qui concerne Selenium et phpUnderControl, ce sont des outils développés en Java. On nous recommande d'utiliser le jre de oracle (comme ce n'est plus Sun...) mais pour ma part j'utilise openjdk sans aucun souci... alors pourquoi passer au propriétaire quand le libre fonctionne très bien ?

Donc, sur votre Fedora ou Centos, préparons un environnement propre... Je vous conseille d'utiliser un conteneur LXC pour bosser, mais si vous voulez utiliser votre système hôte je ne vais pas vous en empêcher.

On commence par installer les outils important:

  • php-cli, php-pear
  • openjdk

on ouvre un terminal, on se met en root et on installe tout ça

su -
yum install php-cli php-pear java-1.7.0-openjdk

Pour la suite, je sais que certains d'entres vous vont me taper sur les doigts, clamant haut et fort que les dépots Fedora ont les paquets PEAR demandés (ou pas...) mais je vais être très clair: les paquets sur les serveurs PEAR sont à jour, et certaines dépendances risquent de ne pas marcher si vous utiliser les RPM. C'est le cas aussi sur Debian (j'en ai fait les frais cette semaine). Donc ayez confiance et faites ce que je dis :)

On commence par faire deux ou trois manipulations sur PEAR pour être à l'aise (toujours en tant que root):

pear set-config auto_discover 1
pear upgrade pear
pear install --alldeps pear.phpunit.de/PHPUnit
pear install --alldeps phpunit/PHPUnit_Selenium
pear install --alldeps pear.phpunit.de/phpcpd
pear install --alldeps phpmd/PHP_PMD
pear install --alldeps PHP_CodeSniffer
pear install --alldeps channel://pear.phpdoc.org/PhpDocumentor-2.0.0a1

Si jamais il vous manque des paquets php, installez les, faites un "prear uninstall" du paquet qui a donné une erreur, et relancez l'installation du paquet.

Vous avez donc à présent:

  • phpunit pour faire des tests unitaires de vos développement php
  • phpunit-selenium qui est une classe permettant de piloter le serveur selenium qui lancera un navigateur pour tester des aspect fonctionnels
  • phpcpd (Copy Paste Detector) qui vérifie les "copier coller" de code
  • phpmd (Mess Detector) qui va vérifier des aspects complexe de code (variables non utilisé, code complexe, nom de variables ou fonctions...)
  • phpcs qui va vérifier si votre code est bien formaté selon des standards choisis
  • phpdocumentor qui permet de créer la documentation de vos projets

Cela étant fait, nous allons passer à la suite... Selenium !

Selenium est un ensemble d'outils qui permettent de piloter un navigateur au travers un serveur. Vous allez pouvoir vérifier si une page apparait correctement, si les liens sont bien présents sur une certaine page, et bien plus encore. Le principe est très simple:

  • on enregistre une séquence de manipulations et de tests
  • on l'exporte pour phpunit
  • on lance le test

Mais pour que cela fonctionne, il faut jouer un peu dans le terminal... rien de bien méchant mais important.

Dans votre terminal, en root, téléchargez le serveur:

mkdir /opt/selenium
cd /opt/selenium
wget http://selenium.googlecode.com/files/selenium-server-standalone-2.20.0.jar

Ce serveur, une fois lancé, pilotera un firefox tout seul. Sauf que voilà... si vous travaillez sur une machine de bureau alors aucun souci ne se profile... mais quand on travaille sur un serveur distant... sans écran... ça va aller mal !

La solution la plus simple, selon moi, est d'installer un firefox "standalone" sur /opt/selenium et de lancer tout ça dans un Xvfb (X virtuel). On va donc faire cela... toujours dans votre répertoire /opt/selenium:

wget "http://download.mozilla.org/?product=firefox-11.0&os=linux&lang=fr"
tar jxf firefox*.bz2

Si tout est ok, vous avez un répertoire "firefox" dans /opt/selenium

On va tenter de lancer firefox dans un X virtuel pour être certain que tout se passe bien:

Xvfb :99 &
DISPLAY=:99 /opt/selenium/firefox/firefox &
DISPLAY=:99 import -window root /tmp/snapshot.png

Maintenant, ouvrez /tmp/snapshot.png et vérifiez que vous voyez bel et bien un firefox ouvert. Si oui: nickel ! si non... heu vérifiez si il ne manque pas une librairie pour firefox (genre gdlib-dbus...)

Bref, si Xvfb et firefox ont marché alors on coupe:

killall Xvfb

Notez qu'on aurait put utiliser "xvb-run /opt/selenium/firefox/firefox" et utiliser le port retourné pour faire la capture, mais les lignes su-citées me paraissent plus explicites pour comprendre comment ça fonctionne.

Bref, utilisons maintenant le serveur selenium pour lancer un test.

Xvfb :99 &
sleep 2
PATH=/opt/selenium/firefox:$PATH DISPLAY=:99 java -jar selenium-server-standalone-2.20.0.jar &

Attendez un peu...il faut voir une ligne indiquant que le serveur tourne, ce genre de ligne:

INFO org.openqa.jetty.http.SocketListener - Started SocketListener on 0.0.0.0:4444
INFO org.openqa.jetty.util.Container - Started org.openqa.jetty.jetty.Server@1ff4689e

Cela peut prendre entre 5 et 30 secondes, soyez patient... A partir de là, le serveur écoute le port 4444, on va donc jouer un peu !

Créer un fichier test.php:

<?php
class Example extends PHPUnit_Extensions_SeleniumTestCase
{
  protected function setUp()
  {
    $this->setBrowser("*chrome");
    $this->setBrowserUrl("http://www.google.fr/");
  }
 
  public function testMyTestCase()
  {
    $this->open("/");
    $this->waitForPageToLoad("30000");
    //on vérifie que "Google" est sur la page...
    $this->verifyTextPresent("Google");
 
    //ce teste doit donner une erreur
    $this->verifyTextPresent("foo bar baz");
 
  }
}

Ce teste ne fait rien de compliqué... il ouvre Google et vérifie si le texte "Google" est sur la page...

Vous pouvez lancer le test:

phpunit test.php

Le résultat doit être:

PHPUnit 3.6.10 by Sebastian Bergmann.

F

Time: 5 seconds, Memory: 5.75Mb

There was 1 failure:

1) Example::testMyTestCase
foo bar baz
Failed asserting that false is true.


FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

Cela indique donc que le serveur selenium a bien lancé firefox, la page google et vérifier qu'un texte "Google" apparait. En ce qui concerne "foo bar baz" cela donne une erreur. Donc:

  • 1 test
  • 2 assertions : texte "Google" et texte "foo bar baz"
  • 1 erreur, et une seule erreur !!! si vous en avez 2 alors c'est que cela n'a pas marché !

Voilà, on peut couper selenium et Xvfb:

killall Xvfb
kill $(ps ax | grep selenium | grep -v grep | awk '{print $1}')

Maintenant, on se crée un service pour lancer Xvfb et Selenium.

Avant tout, pour des raison pratiques, je vous conseille de ne *plus du tout* lancer Xvfb et Selenium en root, mais avec un utilisateur précis. Comme nous allons utiliser phpUnderControl qui est un plugin de cruisecontrol, et que ce dernier lancera son service avec un utilisateur recommandé, nous allons le créer de suite et l'utiliser pour lancer Xvfb et Selenium.

useradd -m -s /bin/bash cruisecontrol

Notez ici que je demande la création du répertoire personnel (via l'option -m) car firefox aura besoin de créer un répertoire de profil, de ce fait, /home/cruisecontrol va être créé.

Voilà, maintenant créons le service qui lance Xvfb et Selenium via cet utilisateur. Créer le fichier /etc/init.d/xselenium et déposez ce code:

#!/bin/bash
 
XLOCK="/var/lock/Xvfb.pid"
SLOCK="/var/lock/selenium.pid"
 
 
startXVFB(){
        [[ -f $XLOCK ]] && echo "Already Running" && return 1
        local PID
        PID=$(su cruisecontrol -c 'Xvfb :15 >/dev/null  2>&1 & echo $!')
        echo "Xvfb pid $PID"
        echo $PID > $XLOCK
 
}
 
startSelenium(){
        [[ -f $SLOCK ]] && echo "Selenium Already Running" && return 1
 
        local PID
        PID=$(su cruisecontrol -c 'PATH=/opt/selenium/firefox:$PATH DISPLAY=:15 java -jar /opt/selenium/selenium-server-standalone-2.20.0.jar >/dev/null 2>&1 & echo $!')
        echo "Selenium pid $PID"
        echo $PID > $SLOCK
}
 
case $1 in
        start)
                echo "Starting XVFB"
                startXVFB
                sleep 2
                echo "Starting Selenium server"
                startSelenium
                sleep 2
                ;;
 
        stop)
                kill $(cat $SLOCK)
                sleep 2
                kill $(cat $XLOCK)
                sleep 2
                rm -f $SLOCK $XLOCK
                ;;
       *)
               echo "$0 start|stop"
               ;;
esac

Rendez le executable:

chmod +x /etc/init.d/xselenium

Et lancez le service:

/etc/init.d.xselenium start

Vous devez donc avoir désormais un Xvfb et un selenium actif. Attendez un peu que le port 4444 soit ouvert pour commencer à lancer les tests, pour vérifier le port:

netstat -taupen | grep 4444

Si aucune ligne n'apparait, c'est que le service ne tourne pas.

Voilà pour la partie pear, selenium-server et Xvfb. Dans la partie 2 nous utiliserons Selenium IDE pour créer des tests, mais surtout nous installerons phpUnderControl afin de piloter notre intégration continue.

En espérant avoir donner quelques clefs...

mercredi, août 3 2011

Un chroot si rapide à créer

J'avais travaillé sur la documentation de chroot sur cette page: http://doc.fedora-fr.org/wiki/Utili... mais depuis, les choses ont changé. Febootstrap ne marche plus du tout comme avant... et j'ai trouvé une manière encore plus simple de créer une base chroot sans manipuler des fichiers de dépôts. Vous allez voir, c'est tellement simple que ça en est presque indécent.

Voilà la manière la plus facile que j'ai trouvé, par exemple pour encapluser "php-cli" dans un chroot:

cd ~
mkdir -p chroots/fedora-15-chroot
cd chroots
su -c 'yum --installroot=`pwd`/fedora-15-chroot --releasever=15 install php-cli -y'

C'est simple comme choux en fait...

Je crée un répertoire dans mon "home" (cd ~ et mkdir -p chroots/fedora-15-chroot). Ensuite je demande à yum d'installer php-cli dans le répertoire fedora-15-chroot. Comme je n'ai pas créé de fichier de dépots Fedora dans le répertoire de chroot, je spécifie simplement que je veux utiliser la version "15" de fedora. Notez que "releasever" est une contraction de "release version".

Et comme par enchantement, j'ai un chroot fonctionnel !

Là où c'est intéressant, c'est que je me passe de pas mal de configuration un peu compliqué. Il est alors facile de changer de --releasever en 16 pour tester la rawhide, ou une version inférieure...

Me reste plus qu'à voir comment fonctionne lxc (et je n'ai pas la dernière version de libvirt donc je n'ai pas encore l'accès facilité par virt-manager) et je vais pouvoir tester pas mal de choses, comme faire marcher des bases en jail, compiler des choses tordus ou voir comment péter un système sans avoir peur :)

samedi, juillet 30 2011

Tester des paquets sans tout casser

Une des raisons pour laquelle j'utilise Fedora depuis des années c'est l'aptitude (clin d'oeil de geek...) de yum à permettre des manipulations de paquets assez rapide. J'avais justement besoin de tester llvm 2.9 qui est pour le moment dans les dépôts rawhide (c'est à dire dans les dépôts de développement de la future version de fedora). Donc, me voilà avec un dilemme: comment tester sans tout casser et sans me prendre la tête à installer une VM? La réponse est dans yum l'ami.

yum a deux options (en fait une commande et une option) qui me permettent de tester sans massacrer mon système: distro-sync et --releasever. La première fait en sorte de synchroniser mes versions de paquets à la version de fedora en cours, et l'autre me permet de spécifier la version de fedora à utiliser.

Et bien allons y gaiement:

su -
yum clean all
yum --releasever=rawhide --nogpgcheck --disablerepos=rpmfusion\* update llvm

Cela à pour effet de lancer une installation en spécifiant que je cherche des paquets pour rawhide. L'installation terminée, j'ai bien un llvm 2.9 qui est installé alors que sur Fedora 15 nous sommes en version 2.8.

Mes tests terminés (et non concluant) j'ai eut envie de revenir à ma version de base. Et bien c'est simple:

yum clean all
yum distro-sync

Et voilà, yum trouve des paquets à downgrader (réduire la version) et me réinstalle tous les paquets estampillés pour la version fedora supérieure à la version actuelle (ici fedora 15). Du coup j'ai resynchronisé ma fedora. Attention tout de même à ne pas faire ça pour n'importe quoi... n'oubliez pas que des fichier .rpmnew peuvent apparaître ou encore peuvent vraiment planter le système.

Personnellement j'évite de faire ça pour tout, par exemple pour le moment j'évite de jouer avec des version de gnome qui se trouve dans rawhide, mais pour ce qui est de certaines librairies, compilateurs, ou encore apache, php... j'aime bien tester de la sorte.

Effectivement lxc ou carrément une machine virtuelle pourrait faire l'affaire, mais c'est tellement sympa avec yum... non ?

vendredi, juillet 22 2011

Jouer avec le bash pour faire un benchmark

Avant toutes choses, je ne suis pas un dieu du bash, loin de là. J'avais besoin de faire un petit benchmark entre node.js, php et python. Et je vous avoues que j'avais pas très envie de créer des scripts partout pour une opération "one shot"... Connaissant un peu les capacités de bash, j'ai tapé instinctivement (je vous assure) les commandes que je vais vous expliquer. Le but était à la base de créer le moins de fichiers possibles. En fait tout ce dont j'avais besoin c'était de créer les fichier de résultats de temps et de visualiser un graphique. Vous allez voir que ce que je vais vous présenter ne crée que 3 fichiers, en fait un fichier de "log" de temps d'exécution par langage. Pour le reste, c'est bash qui va s'occuper de me rendre service, ainsi que le fabuleux gnuplot.

Juste une petite parenthèse, ce billet est surtout là pour montrer à quel point le terminal de commandes est puissant si l'on se penche un peu sur l'ensemble des commandes utiles. Un peu d'entrainement permet de régler des tas de soucis, mais aussi, comme dans mon cas présenté ici, de permettre des travaux qui peuvent paraître compliqués... mais finalement réglé en quelques minutes... Encore une fois, je connais bien Bash et cela vient naturellement, mais je n'ai pas plus d'aptitude que la plupart des linuxiens sur un terminal. Ma seule performance ici est d'avoir la folie et l'amour des lignes de commandes pour ce genre de process.

Très bien, pour être précis mes benchmarks se portaient sur le calcul de 32 rangs de la suite de fibonnacci. Pour ceux qui ne la connaissent pas, je vous la présente rapidement: 0 1 1 2 3 5 8 13 etc...

En fait c'est simple, on part de 0 puis 1, ensuite il faut ajouter les deux nombres précédents pour trouver le nombre du rang "n".

  • 0 et 1 engendre: 0+1=1
  • la suite est donc 0 1 1
  • ensuite je prend les deux derniers chiffres: 1 et 1, je les additionne: 1+1=2
  • la suite devient 0 1 1 2
  • on continue de la même manière, les deux derniers chiffres de la suite étant 1 et 2: 1+2=3
  • la suite devient 0 1 1 2 3
  • et ainsi de suite, les deux derniers chiffre étant 2 et 3: 2+3=5
  • la suite devient 0 1 1 2 3 5
  • etc...

Algorithmiquement, cela peut se résoudre par une fonction itérative:

fonction fibo (n)
    si n vaut 0 ou 1 on retroune n
    sinon on retourne fibo(n-2)+fibo(n-1)

Ok, pour python, php et node (javascript) cela va se faire en 3 ou 4 lignes... et plutôt que de créer un script, je fais appel aux interpréteurs directement en ligne de commande. Par exemple pour avoir le rang 10 en PHP:

php -r '
function fibo ($n) {
return ($n==0 || $n==1) ? $n : fibo($n-1)+fibo($n-2);
}
fibo(10);
'

Ça fonctionne bien.

Reste que je veux calculer tous les rangs allant de 0 à 32... et bien bash me permet de boucler:

for i in $(seq 1 32)
do
php -r '
function fibo ($n) {
return ($n==0 || $n==1) ? $n : fibo($n-1)+fibo($n-2);
}
fibo('$i');
done

Pas mal... mais il me reste un truc à faire, chronométrer le processus... alors oui je sais, il existe la commande "time" mais elle est pas si simple à gérer en terme de sortie, moi j'ai besoin d'avoir juste le temps total, seconde et milisecondes comprises... et bien c'est simple, on va enregistrer le timestamp + les nanosecondes via la commande "date" avant puis après le processus. Il suffira de soustraire les temps pour avoir le différenciel.

Voilà comment je benchmark PHP:

for i in $(seq 1 32); do 
echo -n $i" "
_s=$(date +%s.%N)
php -r '
function fibo ($n) {
return ($n==0 || $n==1) ? $n : fibo($n-1)+fibo($n-2);
}
fibo('$i');
'
echo $(date +%s.%N)-$_s | bc -l
unset _s
done

Je vous explique. je boucle 32 fois sur la suite de commande:

  • echo -n $i" " : pour savoir où j'en suis, j'ajoute un espace après le nombre, et j'utilise "-n" pour ne pas revenir de suite à la ligne
  • _s=$(date +%s.%N) : je place la date en timestamp (nombre de secondes depuis 1970) suivit de "." et les nanosecondes en cours
  • php -r... : on exécute le code php
  • echo $(date +%s.%N)-$_s | bc -l : j'écris l'opération "date courante avec nanoseconde" - "date enregistré avant le process" et je l'envois à "bc -l" qui va calculer ça
  • unset _s : juste pour virer la vairable $_s qui va plus nous servir.

Bon, vous avez compris, me reste plus qu'à enregistrer le résultat dans un fichier. Je vais donc dans /tmp et je crée un répertoire "bench":

mkdir /tmp/bench
cd /tmp/bench

et je fais le logs, pour PHP en premier (dieu que c'est lent...):

for i in $(seq 1 32); do 
echo -n $i" "
_s=$(date +%s.%N)
php -r '
function fibo ($n) {
return ($n==0 || $n==1) ? $n : fibo($n-1)+fibo($n-2);
}
fibo('$i');
'
echo $(date +%s.%N)-$_s | bc -l
unset _s
done>php.log

On fait pareil pour node:

for i in $(seq 1 32)
do
echo -n $i" "; _s=$(date +%s.%N);
node <<JS
function fibo(n) {
return (n==0 || n==1 ) ? n : fibo(n-2)+fibo(n-1);
}
fibo($i);
JS
echo $(date +%s.%N)-$_s | bc -l; 
unset _s; 
done>node.log

et enfin pour python:

for i in $(seq 1 32)
do 
echo -n $i" "
_s=$(date +%s.%N); python -c '
def fibo(n):
   return n if (n==0 or n==1) else fibo(n-1)+fibo(n-2)
fibo('$i')
'
echo $(date +%s.%N)-$_s | bc -l; 
unset _s; 
done>python.log

J'ai donc là 3 fichier qui contiennent chacun des logs de temps, je vous montre celui de PHP:

$ cat php.log 
1 .036828663
2 .025703992
3 .026992606
4 .033444640
5 .035266864
6 .033452564
7 .028677243
8 .036187726
9 .035308338
10 .033860607
11 .030994306
12 .031643060
13 .030666493
14 .033131695
15 .037534009
16 .034849018
17 .036111420
18 .042433952
19 .044907994
20 .052853506
21 .068992452
22 .086515691
23 .125384399
24 .180959996
25 .279442730
26 .412510010
27 .648189657
28 1.019483322
29 1.626384710
30 2.644171263
31 4.257360111
32 6.938595991

Mon souci va être d'utiliser les 3 fichiers en même temps dans gnuplot... plutôt que de passer par 3 commandes en entrée (je vais vous montrer comment on fait dans gnuplot) je vais utiliser une commande que j'adore: paste

Cette commande est magique, elle "colle" en colonnes les fichiers les uns à coté des autres, voici ce que ça donne chez moi:

$ paste *.log
1 .065706975    1 .036828663    1 .051057606
2 .075880231    2 .025703992    2 .046552158
3 .073986169    3 .026992606    3 .046123806
4 .073072239    4 .033444640    4 .042877291
5 .070891448    5 .035266864    5 .045012469
6 .074523262    6 .033452564    6 .047550418
7 .072727132    7 .028677243    7 .042658307
8 .075226716    8 .036187726    8 .045704715
9 .069166717    9 .035308338    9 .046088504
10 .071344391   10 .033860607   10 .043567632
11 .072756556   11 .030994306   11 .043765426
12 .073284181   12 .031643060   12 .043340776
13 .072755513   13 .030666493   13 .045153174
14 .068839918   14 .033131695   14 .047908738
15 .079993544   15 .037534009   15 .050165910
16 .072923693   16 .034849018   16 .048907127
17 .074823342   17 .036111420   17 .047513241
18 .073899009   18 .042433952   18 .053685052
19 .069858333   19 .044907994   19 .048828831
20 .071467252   20 .052853506   20 .050347929
21 .073423093   21 .068992452   21 .049505150
22 .074624496   22 .086515691   22 .060360949
23 .071165563   23 .125384399   23 .068465359
24 .076328627   24 .180959996   24 .079916752
25 .076409643   25 .279442730   25 .100771059
26 .079967605   26 .412510010   26 .136666736
27 .076491429   27 .648189657   27 .198588958
28 .085810737   28 1.019483322  28 .293586222
29 .095436353   29 1.626384710  29 .434787310
30 .104759161   30 2.644171263  30 .675019713
31 .125979134   31 4.257360111  31 1.074293193
32 .155473948   32 6.938595991  32 1.705526686

S'en est presque poétique... non ? Vous avez remarqué qu'on a besoin ici des colonnes 1, 2, 4 et 6 pour avoir la valeur de 'n' et le temps d'exécution pour chaque langage. Notez aussi que les colonnes représentent les fichier dans l'ordre alphabétique du nom du fichier de log, ainsi de gauche à droite on a "node", puis "php" et enfin "python"...

Bon on passe à gnuplot, on lance la commande gnuplot et on tape ceci:

gnuplot> set title "Benchmark Fibonnacci"
gnuplot> set xlabel "n value"
gnuplot> set ylabel "time in seconds"
gnuplot> set grid
gnuplot> plot "< paste *.log" using 1:2 with line title "node", "< paste *.log" using 1:4 with line title "php",  "< paste *.log" using 1:6 with line title "python"

Je sais que j'aurais put utiliser les fichier les uns après les autres mais la commande "paste" me permet des copier/coller rapides de mes commandes sans avoir à changer le nom du fichier à chaque fois... et puis je voulais vous parler de cette commande d'abord hein !

Bref, le résultat est de cette forme: Fibonnacci benchmark gnuplot

Vous l'aurez donc compris, en maitrisant un peu le bash on peut effectuer des opérations assez poitilleuses sans pour autant à avoir à gérer un projet complet de scipts... le tout est de s'entrainer, et tout devient instinctif.

Je le répète, j'ai fait ces opérations sans me poser de questions, et comme je me suis rendu compte que ça pourrait intéresser certains... je me suis dit qu'il serait bon de montrer un peu comment je procède.

Et bien voilà, explication terminée. En espérant que ça vous ait donné envie de taper des lignes de commandes plutôt que de passer par un tableur... ;)

PS: désolé pour les fautes d’orthographe mais j'ai du mal à les trouver ce soir... je corrigerai demain...

dimanche, février 20 2011

Cython pour optimiser Python

Cython permet de coder des extensions python compilées via un mécanisme de traduction en C. Mais il permet aussi de créer un exécutable de votre programme python. Les performances sont spectaculaires et nous allons le voir dans ce billet

Lire la suite...