» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
Aujourd’hui tout le monde parle d’Apple et de Google avec leurs iPad/Phone/Tablet etc. une chose que les gens ont tendance à oublier vite est la manière dont Apple et Google prennent contrôle sur vous quand vous utilisez leurs systèmes :
- Un téléphone Apple ne peut exécuter que des applications contrôlées par Apple (et ce contrôle est particulier).
- Un téléphone Androïd/Google vous demande votre identifiant Google pour la moindre opération ou presque.
Par contre, Nokia reste à distance de tout cela et avec la plate-forme Maemo a une approche ouverte depuis maintenant 5 ans et le Nokia N770 et cela continue, à son rythme, mais avec rigueur et ouverture. C’est quelque chose d’exceptionnel pour une entreprise aussi grosse. Ils ont commencé avant même d’avoir été mis en danger sur leur terrain pour Google/Apple/HTC/LG etc. Alors quand je lis que le dernier N900 est très facile d’utilisation sur une plate-forme totalement ouverte, je repense aux OS (Windows, Linux, etc.) et je me dis, attendons un peu, Nokia va gagner car à qualités égales ils jouent l’ouverture, et c’est bien.
je suis dans la dernière ligne droite qui doit se terminer le 10 janvier d’un sympathique contrat avec un non moins sympathique client. La bonne nouvelle est que si je finis correctement le travail dans les temps, ma petite société aura de quoi payer ses frais de structure et mon salaire jusqu’en septembre/octobre 2010. J’aime commencer l’année ainsi, même si cela est fatiguant. Vous me retrouverez sur les forums etc. à partir du 15, car je vais avoir beaucoup de papier en retard ensuite.
Comment cela fonctionne ? Je me paye un tout petit salaire et je suis très économe dans la gestion de ma société. Dans la vie on n’a qu’une seule ressource vraiment limitée, c’est le temps. Je structure donc ma vie et mon travail pour favoriser le temps de qualité avec des projets qui me passionnent et les gens que j’aime contre moins d’argent à la fin du mois.
En prenant des sources très sérieuses on obtient 86 morts en Allemagne à la date du 10 décembre et 15 morts pour le vaccin. Bien entendu le journal très s’empresse de citer leur source qui annonce que les 15 morts ne sont pas morts du vaccins mais d’autres problèmes (notez que la même source donnait déjà 2 morts confirmés par le vaccin il y a peu). Je vais être gentil pour la langue de bois, on va diviser par 3 ce chiffre. Donc on va dire, 5 morts par le vaccin (ce que le même article confirme indirectement, car ils annoncent de 1 à 10 réactions très importantes par million de doses et on est à 5 millions de vaccins faits en Allemagne).
Donc en prenant l’hypothèse la plus basse pour le vaccin et la plus haute pour la grippe elle-même on obtient :
- grippe, 80 millions de personnes exposées et 80 morts.
- vaccin, 5 millions de personnes vaccinées et 5 morts.
Comme aujourd’hui le pic d’infection est passé en Allemagne ces résultats posent question. Notez que à la dernière lecture de la base de données sur les effets du vaccin, le seul vaccin qui montrait des réactions importantes était le Pandermix, l’autre n’avait pas encore donné de cas de mauvaises réactions.
Je répète donc encore, je ne suis pas contre les vaccins, je suis contre une vaccination de masse, sans distinction, là où les médecins eux-mêmes annoncent qu’il ne faut pas donner le même médicament à tout le monde du fait de problèmes d’intolérance. Pourquoi le double discours, les vaccins c’est bon pour tous et les médicaments il faut faire attention ?
Je vous laisser regarder mes sources, dont le RKI qui centralise toutes les informations sur le sujet des vaccins en Allemagne et sur la politique de la santé.
Google se lance dans le service de DNS. Leur DNS est-il si rapide que cela ?
J’ai utilisé un script pour faire les tests avec les résultats que voici :
Pour OpenDNS, Google et mon routeur, j’ai fait 6x1000 requêtes des 1000 sites les plus importants selon Alexa, pour mon ISP (T-Online), uniquement 3x1000. Vous avez le min, max et la moyenne pour chaque moyenne de la requête DNS par série de test. Ce n’est pas très scientifique de faire ces séries de moyennes mais cela correspond aux informations sorties du script de test.
En gros, mon petit routeur ou votre box est plus rapide que Google et que tout le monde. N’allez pas voir ailleurs ! Maintenant, Google sait qu’il sera toujours plus que votre box/router et c’est pour cela que je n’ai aucune confiance en eux.
Pourquoi savent-ils qu’ils seront toujours plus lent ? C’est le problème de la localité de la mise en cache. Votre routeur n’est qu’un proxy de votre prestataire mais il peut aussi mettre en cache. Vous aurez alors une réponse en quelques millisecondes pour vos sites habituels. Dans mon cas, mon routeur ne fait probablement pas beaucoup de mise en cache (en fait je n’ai aucune idée, en dehors qu’il va plus vite que mon ISP).
Google cherche déjà à installer ses serveurs chez les ISP pour mettre en cache l’information au plus près de vous, utiliser un serveur DNS à l’extérieur comme celui de Google ou OpenDNS est une démarche inverse, la seule raison que je vois c’est de pouvoir encore accumuler plus de données sur les internautes.
Note : Dans la note sur les données personnelles, ils ne gardent les informations que 15 jours. 15 jours, voilà une belle période de temps pour sortir des stats et les inclure dans leur base avant de poubelliser (éventuellement, car en fait personne ne sait) les données brutes.
Chouette, Fabien Potencier vient de lancer Pirium. Pirium, c’est un petit script simple, puissant et élégant pour la création d’un dépôt PEAR pour vos projets PHP.
Oui, je dis du bien de ce script ! C’est un script qui ne fait pas la vaisselle, qui n’a pas 160 classes et en fait qui fait une chose et j’espère le fait bien. Comme tout ce que j’ai utilisé/vu venant de Fabien faisait du bon travail — souvent trop lourd pour moi, mais au final toujours bon — je ne doute pas que Pirium va faire du bon travail.
Attendez-vous à avoir InDefero et Pluf disponibles via un dépôt PEAR sous peu ! Merci Fabien !
Edit: C’est Pirum et en non Pirium. :-/
Il semble qu’un nombre assez importants de faits troublants commencent doucement à remettre en cause toute cette histoire de réchauffement climatique. Je ne sais pas si l’un ou l’autre est vrai, par contre une chose est certaine, une chose me casse les pieds dans la diffusion de l’information sur le sujet. Aujourd’hui on entend régulièrement que un réchauffement de 1°C va faire disparaître X espèces animales et c’est faux pour la très grande majorité d’entre elles. En fait, ce n’est pas le réchauffement climatique, c’est la destruction de l’habitat de ses espèces par les hommes pour pratique une activité qui en plus pourrait contribuer au réchauffement climatique. Regardez en Europe le nombre d’espèces menacées par nos autoroutes, zones industrielles et l’urbanisation galopante. Notre impact négatif sur la planète est bien plus du fait de notre manque de respect pour cette dernière que par notre utilisation du pétrole. C’est cela qui va être dur à changer, la protection de la faune et la flore étant faite toujours à minima…
Au final, cela ne me gène pas que la théorie du réchauffement climatique puisse être fausse et archi fausse. Pourquoi ? Car cela nous apprend à essayer de vivre en équilibre énergétique et à utiliser nos ressources de manière optimale. C’est cela que je trouve le plus intéressant dans toutes les conséquences de cette histoire. Cette recherche d’optimalité va naturellement nous faire penser à notre environnement et donc nous faire respecter les petites grenouilles qui se baladent sur le bord de nos chemins.
Je suis un minimaliste (ou plutôt j’essaye) qui aime l’utilisation optimale des ressources, que cela soit des cycles d’un CPU, de l’essence dans ma bagnole, de la batterie de mon vélo ou simplement de ce que je mange. Avec la fin de l’énergie presque gratuite, nous allons devoir tous nous habituer à cela, alors si le réchauffement climatique peut nous motiver à le faire par avance, je suis pour.
Note : C’est bien la première fois où une mauvaise interprétation de résultats scientifiques ne me dérange pas, car de toute façon, la fin du pétrole nous forcera à suivre ce chemin tôt ou tard et je n’arrive pas à voir les effets négatifs de l’erreur (en dehors de la perte de confiance dans nos institutions, mais qui leur fait encore confiance ?).
C’est en anglais, mais cela vaut la peine d’être lu My Favorite Liar. Comment un professeur menteur peut rendre un cours intéressant.
Lisez et ensuite pensez à l’information que votre télévision vous matraque chaque jour, surtout livrée par Docteur Truc et Expert Bidule. Lisez aussi ce que j’écris avec le même esprit critique, cela me fera plaisir.
Mon professeur préféré était un menteur, j’aurais aimé avoir des profs comme cela.
En deux jours en Allemagne, alors que la phase de vaccination de masse commence tout juste (il faut en effet se faire vacciner d’abord pour la grippe saisonnière et attendre 3 semaines avant de passer au vaccin Pandemrix H1N1) un petit bout de chou de 1 an et un homme de 55 ans sont morts dans les 24h suivants le vaccin. Une petite recherche dans la base de donnée allemande, mise à jour il y a plus de 1 semaine donne déjà plus de 200 cas de complications graves (notez que vous devez valider 7 pages de mises en garde avant d’accéder à la base de données).
Par ailleurs, pour votre information, si vous lisez qu’il y a X cas de grippe A en Allemagne, vous ne pouvez que compter comme certain que les cas de décès. Ils ne font pas de test sur les vivants cela coûte officiellement trop cher. On a donc l’assurance d’un cas une fois mort et autopsié. Le corps médical aujourd’hui n’arrive pas à faire la distinction entre une grippe saisonnière et une grippe A sans faire un test donc les statistiques ne peuvent pas être justes.
Le vaccin en général est un sujet tabou, la personne qui est contre est marquée du sceau du blasphème et ses propos ne sont plus écoutés (un peu comme les détracteurs de la saignée à une certaine époque). Le problème est qu’aujourd’hui, les commissions de validation des vaccins sont présidées par des personnes ayant des liens étroits (souvent de anciens employés) avec les laboratoires pharmaceutiques. La STIKO, qui est la commission allemande, est connue pour faire une opposition systématique à toute publication de résultats remettant en cause certains vaccins (même pas le principe de vaccin, juste un vaccin particulier). Le dernier cas en date est la tentative d’étouffement d’un vaccin 6 maladies pour enfants de 3 mois à 2 ans qui tuait avec une probabilité plus importante que la probabilité cumulée d’avoir une de ces maladies. Le vaccin a depuis été retiré du marché.
Maintenant, pensez au vaccin contre l’hépatite B en France, les cas répétés d’infirmières se choppant la maladie X ou Y alors qu’elles sont très vaccinées et bien d’autres choses étonnantes.
En Allemagne, la littérature assez impartiale sur le sujet est très limitée, le problème est que chaque vaccin est différent mais que pour les vaccins, bizarrement d’un seul coup soit on est contre, soit on est pour, mais on a pas le droit d’être un peu septique. Alors que ces mêmes personnes vont naturellement reconnaître que pour du médicament normal, il y a du bon et du mauvais. Un cas type est par exemple la réaction de Daniel Glazman, dans le domaine technologique il a une analyse très fine des avantages et inconvénients de chaque technologie, pour les vaccins, aucun doute. Si vous le lisez régulièrement vous saurez son point de vue sur certains médicaments.
Le problème du vaccin est que c’est un choc important sur le système immunitaire et que ce choc personne ou presque n’a encore pris le temps d’en analyser les conséquences et que pour stabiliser un vaccin des molécules très complexes (en fait souvent des complexes ioniques) aux effets secondaires difficilement mesurables. Le grand arguments des pros vaccin est la disparition en Europe de certaines maladies depuis les années 50, mais ils ignorent totalement l’amélioration des conditions sanitaires et oublient de dire que dans les années 50, il y avait toujours un bidonville à Paris. Un argument massue pour ne pas rentrer dans les détails.
Tous les vaccins ne sont pas mauvais, mais faire une expérience médicale sur l’ensemble de la population européenne sans aucune assurance de quoi que cela soit est un délit.
On me fait rarement parvenir une offre d’emploi aussi belle, Ecolutis embauche un développeur PHP. Lisez l’offre, même si cela ne vous intéresse pas. Lisez l’offre, surtout si vous voulez un jour embaucher quelqu’un. Lisez l’offre si vous voulez savoir pourquoi la société d’en face trouve de bons développeurs et pas vous. Lisez l’offre si vous voulez découvrir une entreprise qui pratique ce qu’elle prêche. Lisez l’offre si vous cherchez un boulot à 300 mètres de la plage.
Je viens de constater que lentement, je change ma manière d’aborder mes problèmes de programmation mais aussi ma manière de gérer mon entreprise. En fait, je change doucement ma manière d’aborder un problème qui se pose à moi.
Face à un problème, j’avais l’habitude de commencer par regarder la situation actuelle puis agir pour faire changer la situation du point actuel vers l’objectif. L’objectif étant la résolution du dit problème. À la lecture de deux billets, deux phrases ont fait tilt :
we produced a “press release” and a FAQ to further detail the how and why of what would become EC2.
et
My brain was wired to focus on the end-point and work backwards, removing each obstacle in my path or going around them all while keeping the goal in sight.
J’ai alors constaté que c’était maintenant mon approche principale pour aborder un problème sur internet. Je pense que le changement s’est principalement fait depuis que je travaille à augmenter les taux de conversions de mes différents sites. Comme je me concentre sur le taux de conversion, mon objectif devient naturellement enlever tout ce qui bloque ces taux. Une nouvelle déformation professionnelle qui finalement va assez bien avec celle que j’ai de tout optimiser.
Imaginez que vous vouliez tracer des informations dans l’exécution de votre application web, en gros, logger des informations, vous trouverez très facilement des class PHP vous permettant d’ajouter cela dans votre code :
// mon code qui fait quelque chose
$logger->log('Mon information');
Mon_Logger::debug($variable);
// la suite du code etc...
Dans le premier cas vous loggez via une méthode d’un objet, dans le suivant via une méthode statique, cela pourrait aussi être via un code du genre Factory::get('logger')->log('message').
Cette approche a malheureusement 2 problèmes :
- une perte de performance du code en production quand on ne veut pas logger ;
- le manque de contexte au niveau du log, il faut souvent alors ajouter des informations dans le message pour savoir d’où vient le message.
La perte de performance peut être partiellement levée par l’utilisation de l’injection de dépendances et charger ainsi un objet de log stupide, qui ne fera rien à son appel. Mais on garde alors un triple coût au niveau des performances :
- coût de l’injection de dépendance pour charger le bon logger ;
- coût de la génération du message pour ensuite ne rien en faire ;
- coût de l’appel à une méthode statique PHP utilisateur, qui ne fait rien.
Dans Pluf, je n’ai pas proposé de méthode particulière et je laisse les gens utiliser le système de leur choix car je n’avais pas trouvé de méthode qui limite vraiment la perte de performance en production, jusqu’à hier.
PHP dispose des assertions, les assertions permettent d’évaluer un morceau de code et d’agir si le résultat est false. Je vous laisse lire la documentation, c’est rapide.
Les côtés très intéressants des assertions sont :
- on peut les activer et les désactiver dynamiquement ;
- si on passe une chaîne en entrée elle est évaluée comme du code dans le contexte local ;
- on peut récupérer le nom du fichier et la ligne où l’exception a été exécutée via un callback.
Conclusion, vous pouvez mettre votre code à logger dans votre chaîne pour votre exception et si votre logger retourne false votre callback va se faire appeler. Si dans votre logger vous ne faites que stocker temporairement votre message, vous pouvez dans le callback reconstituer l’ensemble des informations et vraiment stocker dans votre fichier de log ou ailleurs.
Voici un bout de code pour illustrer :
<?php
function log_assert($file, $line, $code)
{
$GLOBALS['log'][] = array(
microtime(true),
$file, $line, $code,
isset($GLOBALS['last_assert_res']) ? $GLOBALS['last_assert_res'] : ''
);
$GLOBALS['last_assert_res'] = null;
}
function logger($text)
{
$GLOBALS['last_assert_res'] = $text;
// false va forcer l'appel à log_assert
return false;
}
// Active les assert en les rendant silencieuses
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
assert_options(ASSERT_CALLBACK, 'log_assert');
$assert = array(1, 0);
$n = 10000;
foreach ($assert as $active) {
$GLOBALS['log'] = array();
assert_options(ASSERT_ACTIVE, $active);
$start = microtime(true);
for ($i=0;$i<$n;$i++) {
assert('logger($i.' is an integer')');
}
$time = microtime(true) - $start;
print "Assert active: $active\n";
print "Elapsed time: $time\n";
print "Per call: ".($time/$n)."\n";
print "Log size: ".count($GLOBALS['log'])."\n\n";
if (count($GLOBALS['log'])) {
var_dump($GLOBALS['log'][0]);
print "\n\n";
}
}
Cela vous donnera un résultat du genre :
$ php test.php
Assert active: 1
Elapsed time: 0.403494119644
Per call: 4.03494119644E-5
Log size: 10000
array(5) {
[0]=>
float(1256912192.17)
[1]=>
string(36) "/home/loa/Projects/pluf/tmp/test.php"
[2]=>
int(32)
[3]=>
string(27) "logger($i.' is an integer')"
[4]=>
string(15) "0 is an integer"
}
Assert active: 0
Elapsed time: 0.03799700737
Per call: 3.799700737E-6
Log size: 0
En gros, votre logger est 10x plus rapide en production si il ne logge rien. Le assert('code') coûte autant que le coût d’un appel de la plus simple des fonctions PHP comme is_numeric ou autre, totalement négligeable en mode production. Si on compare avec l’appel à une méthode statique utilisateur qui ne fait rien, le code qui logge ne coûte que 30% de plus ! La fonction assert est donc très optimisée et on peut en profiter.
Et comme vous avez un framework bien fait, vous pouvez toujours faire la chose suivante :
- en fonction de la requête (cookie, url, etc) activer ou non le log ;
- accumuler les logs pendant la requête ;
- stocker le log dans memcache ou APC en fin de requête ;
- flusher les informations sur le disque ou dans votre base de données toutes les x requêtes/minutes.
Notez que c’est la seule manière d’avoir le contexte du message au meilleur coût (pas d’introspection). Un inconvénient quand même, votre message est l’évaluation d’une chaîne de caractères, donc cela se lit moins bien dans le code. J’ai quand même trouvé une méthode pour logger dans Pluf, chouette.
Le rappel de l’existence de assert m’a été fait par François dans les commentaires ici, merci !
Mise à jour: Ceci est une utilisation détournée de la fonction assert, cela peut poser des problèmes si vous combinez cette approche avec du code utilisant assert pour réellement faire des tests. Ce qui me rassure c’est que dans l’intégralité du code PHP que j’utilise, incluant de nombreuses bibliothèques issues de PEAR, je n’ai pas trouvé une seule utilisation de assert.
Si vous faites du type hinting, c’est qu’à priori vous faites très attention à la structure de vos projets PHP. Si vous avez un code du type :
function maFonction(MaClass $objet) {
// corps de la fonction
$objet->faitTruc();
echo $objet->bidule;
}
vous n’acceptez que des objets de type MaClass en entrée. Supposons que maintenant, une personne veuille utiliser votre fonction avec un objet de la class AutreClass en sachant très bien que son objet fourni les méthodes et propriétés nécessaires à maFonction. Il ne peut pas car AutreClass n’est pas MaClass.
Une approche élégante si vous voulez donner de la flexibilité à vos utilisateurs finaux est de dire : "J’accepte tous les objets qui implémentent la bonne interface.".
function maFonction(IMaClass $objet) {
// corps de la fonction
$objet->faitTruc();
echo $objet->bidule;
}
Maintenant, il suffit que AutreClass implémente l’interface IMaClass pour satisfaire maFonction. Cela donne de la flexibilité tout en forçant un peu de contrôle car PHP au niveau du langage va forcer le respect de ce contrat entre maFonction et le paramètre. Si vous avez une utilisation parcimonieuse des interfaces dans vos logiques métier (histoire d’éviter d’avoir ensuite des class qui implémentent 5 interfaces ou plus), cela vous donne une certaine assurance, surtout si votre code est ensuite utilisé par d’autres entités dans votre société. Vous êtes certain que la personne a été obligée d’implémenter l’interface avant d’utiliser votre fonction.
Une autre approche est de demander de manière implicite l’interface sans jamais le déclarer réellement dans le code. C’est à dire que la fonction va accepter n’importe quoi :
function maFonction($objet) {
// corps de la fonction
$objet->faitTruc();
echo $objet->bidule;
}
C’est alors au moment de l’exécution dans la fonction que PHP va retourner une erreur si l’interface implicite n’est pas respectée. Ceci peut être très mauvais dans certains cas. Si on suppose que maFonction fait une série d’opérations sur des fichiers et que l’objet fournit les chemins nécessaires :
function maFonction($objet) {
grosse_copie($objet->source(), $objet->destination());
nettoyage($objet->sourceExcludeBackup());
echo $objet->bidule;
}
On va supposer que grosse_copie fait une grosse copie de fichiers de la source vers la destination et que nettoyage va ensuite nettoyer la source mais garder le backup. Dans ce cas là, si l’objet ne fournit pas la méthode sourceExcludeBackup, PHP va s’arrêter après la grosse copie et laisser votre système dans un mauvais état. En ayant utiliser le type hinting, PHP n’aurait même pas commencé l’exécution de maFonction, le système aurait été protégé.
Le type hinting et les interfaces ont un impact au niveau des performances et complexifie le code, donc ces outils doivent être utilisés avec soin, particulièrement dans le cœur d’exécution de votre programme mais ces outils apportent une sécurité indéniable dans certains cas particuliers, surtout dans la logique métier, là où le non respect d’une interface explicite ou implicite peut faire des dégâts.
Un endroit où je n’utiliserais pas le type hinting et les interfaces est par exemple la boucle de dispatch dans une application web. De toute façon si vos objets de requête et de réponses n’implémentent pas les bonnes méthodes, vous allez vite vous en rendre compte et les dégâts seront une requête plantée. L’erreur ne prendra pas longtemps pour être trouvée et corrigée, et dans tous les autres cas vous payerez le prix au niveau des performances, ce qui serait dommage.
Bien utilisée, la combinaison type hinting et interfaces peut donc se montrer être un outil très puissant de contrôle de la qualité.
Si vous ne connaissez pas Pluf, le framework PHP le plus rapide du monde, je vous invite à lire une petit brève ici et un benchmark de framework PHP là, vous pouvez aussi lire comment je tire à vue sur certains développements ici avec un benchmark de template PHP là.
Pluf, le framework PHP le plus rapide du monde, c’est aussi un joli troll dans les chaumières des développeurs PHP, il semble que cela commence même à troller dans les SSII sur le sujet. Aïe, pour un programmeur, voir son code être le sujet d’un troll, cela peut paraître ennuyeux, mais dans mon cas, cela me fait très plaisir. Je ne suis pas sado, loin de là, mais essayer de faire passer une idée qui va à l’encontre des pratiques du moment est toujours difficile.
Donc à toutes les personnes qui se moquent, je vous dis merci, et je vous dis surtout continuez ! Continuez de troller sur la rapidité du framework X par rapport au Y.
Maintenant pourquoi je tape sur les bibliothèques et frameworks PHP qui ne font que prendre du poids avec le temps ?
InDefero est une application web dite de forge logicielle. Vous pouvez au choix la télécharger (licence GPL) ou profiter d’un hébergement pour vous contre quelques Euros. L’hébergement InDefero c’est 1500 forges dont 1300 d’actives. Quand vous gérez cela, vous gérez un système qui au niveau performance doit supporter 50 à 100 fois plus de charge qu’une installation unique (la charge se répartie dans la journée avec les fuseaux horaires, donc ce n’est pas un facteur 1000).
Un facteur de 50 à 100, cela veut dire que très rapidement, si vous utilisez des bibliothèques qui font trop, votre composant web va s’essouffler, en gros votre serveur web ne va plus ternir la charge tout seul. Il faut être réaliste, dans la majorité des applications web, la logique métier est principalement de la requête sur la base de données. Donc on peut faire un calcul simple, de derrière d’une enveloppe et décomposer une requête web en 2 parties, logique métier et framework :
- logique métier: 50ms par requête ;
- logique framework: 50ms par requête.
On obtient donc une réponse en 100ms pour une requête, performance tout à fait honorable, on va l’appeler le cas optimisé.
Maintenant, je tape dès que je vais des facteurs 3 à 5 sur les performances des bibliothèques. Comme la logique métier est incompressible on obtient :
- logique métier: 50 ms par requête (ne change pas) ;
- logique framework: environ 150 ms par requête (facteur 3).
Total 200 ms, un facteur 2.
Cela veut dire quoi ? Cela veut dire que votre ensemble DB + serveur web va avoir besoin de 2 fois plus de cycles CPU pour servir la même charge. Cela veut dire que votre coût pour faire croître votre site va être multiplié par 2.
En fait c’est pas très juste, le premier goulot dans une architecture share nothing est toujours la base de données. Donc dès que le système ne tient plus, on déporte la base sur son serveur propre. Maintenant, on refait le calcul mais on prend en compte la distinction serveur de BD et serveur Web.
Version optimisée par requête :
- logique métier: 50ms par requête (serveur BD) ;
- logique framework: 50ms par requête (serveur Web).
Version lourde :
- logique métier: 50 ms par requête (ne change pas, serveur BD) ;
- logique framework: environ 150 ms par requête (facteur 3, serveur Web).
Maintenant, si on suppose que dans le cas optimisé un serveur web peut saturer un serveur de BD, on obtient pour assurer la même charge :
- Version optimisée : 1 serveur web et 1 serveur de base de données.
- Version lourde : 3 serveurs web et 1 serveur de base de données.
Facteur 2 au total, mais un facteur 3 sur le front end. Je vous laisse penser à tous les problèmes de répartition de la charge et de synchronisation du code que cela implique ainsi que les coûts associés. Bien entendu c’est du calcul de dos d’enveloppe donc à prendre comme un ordre de grandeur surtout l’approximation logique métier équivalente aux requêtes vers la base de données.
Pourquoi un différence si importante ? Car à tous les échelons, le choix à été fait de prendre la solution qui fait plus au cas où qui n’arrive dans 99% des cas jamais mais qui coûte 3 fois plus de cycles. L’agilité c’est introduire dans un système la complexité strictement nécessaire et suffisante en choisissant les bons outils et en refactorisant en continu. C’est très dur (j’ai vraiment du mal) mais cela vaut la peine !
Note pour les trolls : je pars en WE et ne vais avoir le temps de répondre que lundi.
Si vous ne connaissez pas Erlang prenez le temps de vous documenter un peu sur le sujet et revenez.
Une chose que j’aime beaucoup avec Erlang et la philosophie suivante :
C’est une philosophie non conventionnelle dans le domaine de la programmation de systèmes complexes et pourtant elle fonctionne très très bien. Elle fonctionne très bien non pas parce que les programmeurs Erlang sont meilleurs que les autres, mais de part la nature du langage et de la VM associées et par l’utilisation abondante du principe :
Check at the interfaces and trust inside.
Grosso modo, faites votre travail de vérification en entrée mais ensuite faites confiance une fois les données dedans.
La rapidité de Pluf provient en très grande partie de l’application de ces choix, pas de type hiting, pas d’interfaces, le minimun de vérifications en interne et surtout un error_handler qui va très joliment retourner toutes les erreurs aux administrateurs avec une copie de la pile.
Pourquoi pas de type hinting et pas d’interfaces ?
Je réponds par une question : Pourquoi forcer le type et l’interface au niveau du code quand cela coûte des cycles d’exécution et que de toute façon vous faites des tests unitaires de vos programmes ? Quel bénéfice cela apporte-t’il vraiment ? Quel problème peut apporter le duck typing ?
La performance de PHP vient de sa simplicité, la résilience d’Erlang vient de la simplicité de son modèle de process… La performance vient du dépouillement pour aller à l’essentiel.
Saint Exupéry écrivait "Il semble que la perfection soit atteinte non quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien à retrancher.
" et ce qui aurait très bien pu être la réponse d’Einstein : "Everything should be made as simple as possible, but not simpler."
Note : Je ne suis pas un programmeur de formation, mon travail qui me fait vivre est d’optimiser ça, j’ai donc une déformation professionnelle pour la simplicité et la performance et je prends donc des raccourcis dans le formalisme de la programmation. Chacun voit midi à sa porte, c’est bien connu.
Mise à jour : Un test "rigoureux" est disponible maintenant.
Fabien Potencier vient d’annnoncer Twig un système de gabarits pour PHP. En dehors du fait que le texte d’annonce commence par quelque chose qui ressemble à du copier/coller de la documentation du framework PHP Pluf, ce qui m’honore, le projet annonce des fonctionnalités exclusives qui en fait ne le sont pas.
Cela fait plus de 2 ans que Pluf propose l’auto échappement des variables dans les gabarits et cela même avant Django. Regardez le système de gabarit de Jelix dont est issu celui de Pluf, tout est dedans (sauf peut-être l’héritage mais il est dans celui de Pluf). Vous constaterez d’ailleurs que Fabien se garde bien de mentionner ces systèmes dans son article… manifestement il connaît bien les effets marketing des omissions bien choisies comme nos amis de Microsoft, Apple, etc…
Et c’est stupide, carTwig apporte une valeur ajoutée certaine, le mode "bac à sable" qui permet l’exécution dans un contexte restreint. C’est là la réelle valeur ajoutée de ce système de gabarit car tout le reste existe déjà, alors pourquoi ne pas mettre l’accent dessus ?
Mise à jour: Twig c’est une bibliothèque de presque 100 fichiers et 160ko, le système de templates de Pluf c’est 10 fichiers dans 70ko en comptant les tags optionnels et les exemples. J’ai un nouveau slogan pour Sensio, "Nos produits sont conçus pour vendre du service associés et des clusters pour votre application web!". Les DSI doivent se frotter les mains, cela leur fait plus de chiffre à gérer. Mais bon, je préfère l’agilité et la légèreté, chacun son truc.
Mise à jour le 10 octobre: Twig est très rapide, mais après un petit coup de xdebug (les 15 premières minutes que je passe pour optimiser le code du système de Pluf) je passe de 5% plus lent à 5% plus rapide que Twig.
Mise à jour 10 minutes après: Le benchmark de Fabien n’est pas correct on va dire. Twig est 4 fois plus lent que Pluf_Template pour 1000 rendu d’une itération sur 1000 éléments ! En gros, c’est un benchmark calculé pour le cas idéal de Twig. Par contre il y a une bonne idée dans Twig que je vais inclure dans Pluf_Template. Au lieu de faire un include à chaque rendu, le code PHP est en fait une classe avec une méthode de rendu. Donc pas besoin de 1000 include. En pratique, dans une application web, cela ne change pas grand chose, car généralement on ne fait le rendu que de 2 ou 3 templates au maximum par requête. Je vais creuser cela même si Pluf_Template est déjà plus rapide et sera toujours plus rapide que Twig. Pourquoi ? Car il fait nettement moins pour aboutir à la même chose. La meilleure façon d’aller vite est de reste simple et ne rien faire d’inutile.
Mise à jour finale ? En implémentant l’idée de la class par template, Pluf_Template est 3 à 4 fois plus rapide que Twig dans tous les scénarii. Je mets en ligne le code demain soir, car là c’est du code rapide entre les petits fours d’un mariage.
La sortie de Twig annoncée par Fabien Potencier m’avait fait hurler. Twig est un système de gabarits pour PHP comme il en existe des centaines. En fait, au bout d’un certain temps, tout développeur s’est essayé à la création d’un système de gabarits/templates pour bien délimiter la logique métier de la présentation.
J’ai hurlé car Twig est une très grosse bibliothèque (presque 100 fichiers) et que cela m’a fait tout de suite penser à mes tests de performances de Pluf.
Je n’avais jamais fait la moindre optimisation du système de gabarits de Pluf et ma version n’est qu’une version simplifiée et étendue de jTpl, le système du framework Jelix, une bonne occasion de faire des tests.
J’ai d’abord mis en place des tests dont voici l’archive complète. Les premiers runs ne montraient pas de différence significative entre Twig et Pluf_Template. Frustration, comment Twig, pouvait être grosso modo aussi rapide que Pluf_Template ?
Un petit tour dans les entrailles de Twig via xdebug et je découvre que :
- effectivement Twig est très lourd ;
- mais que l’auteur est futé, le test est taillé sur mesure pour favoriser Twig.
Twig compile les gabarits en une ou plusieurs classes PHP, donc un rendu n’est qu’un appel à une fonction d’une classe. Pas besoin de faire un include comme pour Pluf. Twig génère des classes lourdes en réinventant PHP, d’où le besoin de ne faire que 3 itérations affichages dans ces tests car sinon les performances se dégradent trop. Un rendu ne devient dans ce test qu’un echo et 3 appels de fonctions.
J’ai donc repris cette idée d’une classe par gabarit et fais quelques petites optimisations par endroits, voici les résultats pour le gabarit Twig suivant :
base.html :
{% autoescape on %}<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="main.css" />
{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
{% endautoescape %}
content.html :
{% extends "tbase.html" %}
{% block content %}
{% for item in items %} item {% endfor %}
{% endblock %}
Vraiment très simple, en fait un peu trop simple mais cela correspond aux tests faits par Fabien, donc cela permettra de faire une comparaison.
Les tests ont été faits sur 3 et 50 éléments dans items avec respectivement 10000 et 1000 rendus. Pour chaque test, 10 runs et les 9 meilleurs ont été conservés. Tous les temps sont sans le coût de la compilation.
Performances
| Système | Test | Rendus/s | Comparaison |
| Twig | 3/10000 | 13767 | - |
| Pluf | 3/10000 | 35151 | 2.55 fois plus rapide |
| Twig | 50/1000 | 1325 | - |
| Pluf | 50/1000 | 4300 | 3.24 fois plus rapide |
Twig est nettement plus lent, rien à commenter.
Mémoire
| Système | Test | Pic mémoire avec compilation (ko) | Pic mémoire sans (ko) | Comparaison |
| Twig | 3 itérations/1 renbu | 996 | 342 | - |
| Pluf | 3 itérations/1 rendu | 490 | 263 | 1.3 à 2 fois moins gourmand |
| Twig | 50/1000 | 1330 | 691 | - |
| Pluf | 50/1000 | 495 | 265 | 2.6 fois moins gourmand |
Les chiffres parlent d’eux-même, mais surtout, ce que je trouve très étonnant, c’est l’augmentation de l’utilisation mémoire de manière aussi importante de Twig en fonction du nombre de rendus. Des objets qui perdent de la mémoire ? Ce n’est pas très propre et je n’arrive pas à m’expliquer ces différences. Le temps de compilation est accessoire, Pluf_Template ne peut que être plus rapide mais on peut très bien précompiler tous les gabarits.
Maintenant, pourquoi battre Pluf_Template sera très dur pour quiconque ?
- Compilation : Laurent Jouanneau a eu la meilleure idée qui soit, Pluf_Template utilise directement le tokenizer de PHP, c’est le code C le mieux optimisé de PHP.
- Exécution : Le code PHP résultant est du code avec le minimum de constructions et d’appels à des fonctions. Le seul gros travail est l’autoescaping. Chose qui ne peut pas être évité dans la majorité des cas.
Conclusion
Vive le logiciel libre et la simplicité. La simplicité de Pluf_Template m’a permis d’améliorer ses performances en moins de 30 minutes grâce à ce que j’avais appris via le code de Twig. Gardez vos frameworks légers pour que la mascotte de PHP ne devienne pas un objet de moqueries…
Si vous vous demandez pourquoi je ne réponds pas à vos emails sur ma boite perso, toute la raison est dans le titre. Je suis totalement noyé. Je viens de finir de remettre mon inbox professionnelle en ordre, mais pour l’autre cela va être bien plus difficile il me semble. Je vais probablement retrouver le contrôle en septembre pendant mes vacances en France. Quand tout le monde sera couché, rien de tel que de faire du nettoyage tranquillement.
Merci de votre patience…
Pour qu’il puisse voir les limitations de mon appareil en mode macro joliment.
Si cela vous dit quelque chose et si cela vous intéresse, je raconte mon expérience dans le domaine du marketing pour un petit ISV et de mes tests AB sur blog.incontexto.com. C’est en anglais mais ce n’est pas bien compliqué.
Une seule remarque : du bonheur. Le disque SSD donne une impression de performance native. Comme je fais beaucoup de développement sous Windows en ce moment, je peux très agréablement utiliser le couple VMWare/Windows. Mes projets dans Visual Studio se chargent plus vite que Windows en natif sur disque "normal". Oui, j’ai passé ma station de travail avec un disque SSD, je n’ai donc plus qu’un unique ventilateur de 120mm à basse vitesse en fonctionnement, le silence est là…







