Javascript et PHP sont-ils des sources de ralentissements ?
Je vais me faire des amis avec un titre comme celui-là
Maintenant, au-delà de la provoque, menons une analyse objective.
Nous avons, de nos jours, (au moins) deux gros goulots d’étranglement lorsque nous nous adressons à un site Web :
- Javascript du coté du client
- PHP du coté du serveur.
Analyse…
Parlons de Javascript…
En général, je m’intéresse plus aux performances des serveurs que des clients au sens “navigateurs”. En réalité, la performance des clients est en générale très liée à celle des serveurs pour être plus précis. Mais le serveur ne peux pas toujours tout.
Notamment les browsers encaissent plus ou moins bien le Javascript et surtout beaucoup de Javascript.
Opera, Chrome, Firefox, Internet Explorer et leurs copains ont une tendance très nette à réagir différemment (je n’apprends rien aux développeurs Web) et surtout à réagir plus ou moins bien et plus ou moins vite en interprétation de Javascript. De plus, ces différences se cumulent avec des comportements très différents d’un browser à l’autre, notamment le nombre de requêtes concurrentes (nombres d’éléments de la page chargé en parallèle).
Tous les sites récents utilisent énormément de Javascript et ont donc une belle tendance à charger la mule, surtout quand on a plusieurs onglets d’ouverts sur plusieurs sites, on a tout de suite des machine virtuelle javascript au sein des navigateurs qui se mettent à grossir.
Ok, so what ? Qu’est ce que j’y peux me réponde les développeurs…
Eh bien beaucoup de choses en fait. Déjà, un framework c’est bien mais ca n’empêche pas de réfléchir. Faire confiance aveuglément sans regarder le dessous des cartes, c’est ce qui mène au gâchis de ressources.
Optimiser ces points (comme d’autres), c’est ce que j’appelle la “culture atari / amiga”. En gros, à l’époque, les développeurs avaient des machines identiques, des machines avec des limites et on pensait à tirer le meilleur partie du Hardware, on optimisait son programme à la goutte prêt, on passait au plus proche du matériel pour faire des choses que les concepteurs de ces machines n’avaient même pas imaginé.
De nos jours, on prend un framework, on instancie un objet et hop, derrière ca pédale mais c’est plus mon problème… Revenons à Javascript.
Des soucis de tableaux !
Il y a de nombreuses sources de maux dans Javascript, langage qui devient incontournable sur le Web depuis 5 ans. Mais lorsque les sites traitent de sujets plus complexes ou offres de nouveaux raffinement, ce qui était “une brique parmi d’autres” devient plus sensible.
Commençons par un soucis simple de Javascript : les tableaux.
Allouer un tableau en JS déclenche des mécanismes très différents d’un malloc en C. Allons y ! Sous IE, la logique de traitement est la suivante :
var my_array = new Array();
for (i = 0; i < 100000; i ++)
my_array[i] = i;
1°) Je crée un objet array qui est une table de hashage.
2°) Comme une table de hashage est un objet générique, je lui crée un attribue length (taille) et on le met à 0
3°) La boucle fait, pour chaque valeur de i
- Une conversion de i en string (chaine de caractère, en gros i= « i »)
- Ajoute un clef de hash pour chaque couple « chaine i », i
- Réajuste la valeur de length
OMG. Donc, rien que pour assigner une valeur au tableau, on a fait 3 opérations (dont deux totalement inutile si on a codé un jour en C).
Pour compléter le tableau, les allocations réelles de mémoire ne sont pas continues car les tableaux sont gérés sous la forme de « sparse » array.
C’est avantageux en terme d’usage réel de la RAM car les blocks vides ne sont pas alloués, par contre les allocations ne sont pas contigüe. Du coup, les accès à ces blocks de données ne se font pas à la suite et n’utilise pas certains mécanismes de prédiction des processeurs ou certains caches des OS. De plus les entrées du tableau ne sont pas indexées.
Bon, maintenant, on a tout pour faire une usine à gaz de compétition !
Pour résoudre ce premier point, sous IE 8, le « sparse array » est détecté comme étant dense ou non. En gros il est très peuplé ou non. Pour que l’heuristique de IE8 comprenne que c’est un « dense sparse array », il faut que ce tableau soit d’une taille explicite (en théorie mais un autre blog ne dénote pas de différence de perfs sur ce point) par contre, il faut en initialiser tous les éléments. Le défaut c’est que toute la RAM est allouée et le coté « sparse » disparait.
Sur un gros PC ce n’est pas si dramatique mais sur un téléphone portable, ouch… Du coup, initialiser l’ensemble du tableau n’est pas toujours la bonne option. Un comportement optimal serait de détecter le navigateur et de lui proposer un Javascript optimisé pour le ratio Rapidité, consommation de CPU & RAM, logique de traitement. Une sorte de librairie optimisée de gestion des tableaux, dépendante de la plateforme qui l’exécute.
En termes d’impacts c’est non négligeable !
Quelques très bon liens pour ceux que ca intéresse. Le premier blog a d’ailleurs de très bons papiers d’une manière générale !
http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/
http://www.outofwhatbox.com/blog/2009/12/javascript-array-performance-and-why-it-matters/
http://blogs.msdn.com/jscript/archive/2008/03/25/performance-optimization-of-arrays-part-i.aspx
PHP et les performances : plantons le décor
Revenons à nos serveurs ! Dans une infrastructure Magento, ce qui pompe dur au niveau des performances, c’est PHP et de très loin.
Il faut évidemment de la RAM pour accélérer les accès et traiter les données mais les appels PHP coutent très chers. Et c’est bien logique car le Web est coincé dans un incroyable paradoxe.
Les langages interprétés (comme PHP) sont très adaptés à certains traitements mais d’une manière générale, pour tous les traitements répétitifs ou massifs, on les évite.
L’idée c’est que dans la rapidité des langages, l’échelle est très claire :
Les compilés :
Les langages ASM/C et C++ sont compilés et (donc) très rapides. On décrit le code et cela se transforme en Opcode directement interprétables et optimisables par le processeur. Tous les caches deviennent super efficaces (L1/L2/L3 du processeur notamment) et le programme traite les données au fil de l’eau et au fil du temps. Le programme se charge en mémoire, il ne s’arrête que quand on lui demande et peut sommeiller le temps d’attendre son prochain traitement.
Assembleur : niveau processeur directement, très peu voir pas d’interprétation, vitesse maximale.
C : Le code produit par un compilateur C est très proche de l’assembleur et donc extrêmement rapide. Pour autant cela reste un langage relativement évolué, contrairement à l’assembleur on a pas à tout écrire de zéro, des librairies existent, des includes, du code un peu évolué d’une manière générale.
C++ : Un langage C évolué et Objet. On monte encore un peu dans les couches, on fait de l’objet et du fonctionnel, on en est plus à la douce barbarie redoutablement efficace de l’assembleur mais ca reste un code qui, une fois compilé, est redoutablement efficace.
Très peu souples en typage ou en gestion de la mémoire, ces trois langages compilés, pour ne citer qu’eux, sont extrêmement rapides !
La machines virtuelles :
Ce sont des programmes qui crée un environnement permettant d’exécuter d’autres programmes en leur sein. L’intérêt essentiel est de s’affranchir de la couche en dessous, en gros le programme devient portable partout. Si la VM existe pour l’environnement matériel cible, le programme tournera (presque) à l’identique sans rien redévelopper. L’inconvénient, comme toute forme de virtualisation, c’est que la VM consomme de la ressource pour créer cette couche d’abstraction, bilan ces langages ne sont pas toujours des foudres de guerre.
Java et autres JVM
Java est le plus connu des langages tournant dans une machine virtuelle, la JVM. C’est un bon langage, objet, évolué et indépendant du matériel mais il souffre de devoir être compilé tout en étant pas aussi rapide qu’un autre langage compilé.
Les « interprétés » :
Aïe. Perl, PHP et de nombreux copains à eux sont des langages dits « interprétés ». A chaque fois qu’il est lancé, le programme (test.php par exemple) est lu par un interpréteur externe (php par exemple), le fichier est parcouru, compilé à la volée quelque part, mais une fois finit, on repart de zéro. Le fichier programme à interpréter est donc lu à chaque fois et le programme qui le lit, l’interpréteur, est un programme qui est lui chargé à chaque exécution aussi.
PHP :
Un des plus célèbres. Zend au dessus est en fait composé de PHP objet évolué au sein d’un Framework, encore une couche d’abstraction. Donc si l’on compare avec nos précédents amis, Zend c’est le C++, Php le C sauf que tout cela est lu/chargé/parsé/interprété puis exécuté en continu. C’est un peu comme si on avait à se taper la compilation a chaque fois qu’on lance le programme… En fait l’image est très exacte puisque c’est quasiment exactement ce qui se passe. Bilan, les langages interprété c’est pratique, facile à maintenir et programmer, on s’affranchit de tous les aspects un peu rigoureux d’allocation mémoire ou de gestion des taches de bases mais le coût en terme de performances est énorme.
PS : Javascript est un langage de scripting interprété tournant dans une machine virtuelle (navigateur)… Tout pour gagner J
Vers un PHP compilé ?
Comme signalé plus haut, l’interprété c’est consommateur et pas adapté aux traitements récurrents. Maintenant si l’on considère une architecture d’hébergement Web, que se passe-t-il.
Admettons que le site soit en Magento, on a un framework de deuxième niveau, qui repose sur un framework de premier niveau (Zend) qui repose sur un langage interprété objet (PHP5) qui repose sur un interpréteur (Php) qui lui-même est compilé et s’adresse en assembleur au processeur.
Ajoutez un peu de virtualisation là-dessus et avant qu’une requête ne passe à travers tout ce maillage, vous avez perdu une quantité de puissance tout proprement hallucinante !
En soit, aucun reproche au fait d’utiliser PHP ou sa syntaxe, par contre, soyons clairs l’approche est juste complètement aberrante. En fait si on essayait de faire pire, le seul moyen, ca serait de faire tourner l’interpréteur php dans une JVM…
Et oui, ce n’est pas anodin mais bien dramatique. A chaque fichier PHP que vous chargez, l’interpréteur est lancé. A chaque fichier php de chargez, vous provoquez toute la cascade de compilation, d’accès disque, d’exécution. Quand un visiteur passe, il provoque donc des centaines de lancement du programme PHP qui va interpréter autant de fichiers… C’est une boucherie, une hémorragie de puissance pour finalement un problème très bête.
Le problème ce n’est pas Magento, Zend ou les fichiers PHP en soit. Sortons de la barbarie de l’assembleur, vive l’objet et tout et tout, on développe plus vite, on réutilise du code, on capitalise des librairies ! C’est l’avancement logique, l’avenir, donc ca va continuer à se développer. Par contre, pourquoi on ne compile pas tout cela ?
La charge CPU des serveurs serait juste divisée par un facteur 10 à vue de nez… C’est à ce point négligeable ? Plus clairement, sur un serveur, au lieu d’accueillir 20 000 personnes par jours par exemple, on en accueillerait 200 000. Avec le même serveur. L’approximation est un peu grossière mais pas outrancière non plus.
Le Web, qui par essence provoque des milliers de lecture et interprétation de fichier de programme, utilise un système d’interprétation, ce qui est la pire façon de faire, ce qui est le plus consommateur possible. Voici le paradoxe.
Si je me la faisais à la Yann Arthus-Bertrand, je redirais « alors pourquoi toi, homo sapiens sapiens, ne compile tu pas tes langages Web ?». Es-tu conscient des ressources gâchées par cette hérésie et de l’impact, de l’empreinte carbone, de cette approche incompréhensible ? Tu veux vraiment défoncer les puits de soleil ? Tu es un inconscient pathologique, un criminel notoire, un serial-gâcheur ? Ooops, je m’emporte… Yann (dont j’aime beaucoup le travail mais un peu moins la voix monocorde) n’irait pas jusque là !
« Pourquoi ne compile t’on pas ? », bon ok, j’arrête de faire mon YAB…
Je n’ai rien contre les développeurs, qui n’y peuvent pas grand-chose si ce n’est optimiser leur code (ca serait déjà un bon début pour certain ceci étant). Ce qui me froisse par contre, c’est que l’on a pas encore de solutions parfaitement mûres pour corriger ce point.
Des soucis assez complexes de conception sont au rendez-vous pour passer du PHP de l’état interprétable à l’état compilé. Mais ne vous y trompez pas, le Graal est au bout de la route.
Plusieurs initiatives sont en cour de développement par des gens talentueux que je ne peux qu’encourager dans cette voie : Roadsend et PHC (Php compiler mais qui paraît à l’arrêt) semblent être les leaders dans cette voie.
http://www.roadsend.com/home/index.php?pageID=compiler
L’autre approche possible serait un cache plus efficace, pas uniquement des opcodes comme APC mais bien des pages rendues, du résultat de l’interprétation PHP. C’est ce vers quoi se dirige Zend Server, c’est une bonne première transition mais le compilateur serait bien LA solution !
En conclusion
Je dirais que PHP et surtout le modèle interprété qui va avec et Javascript et surtout l’implémentation qui en ait faite des les navigateurs autant que dans le code de certaines pages Web, sont deux problèmes.
Ces deux axes de progression nous apporteraient un Web plus rapide, souple et agréable d’utilisation. Le réseau n’est plus réellement une limite, les processeurs sont suffisamment puissants alors deux cas sont possibles :
- Quelques personnes douées arrivent au bout de ces deux problèmes
- Tout le monde se contente de ce qu’on a, on enterre la logique d’optimisation de l’époque atari & amiga, on tue les phoques et la banquise en consommant inutilement des ressources informatiques précieuses. On compense par plus de puissance, plus de ressources consommées, plutôt que de mieux utiliser.
Un classique me direz-vous ?
Pas de posts similaires.
décembre 20th, 2009 at 21 h 47 min
Bonne analyse..le PHP compilé c’est un peu comme le JAVA sans JVM ca fait rêver tout le monde
Ensuite il y a un problème économique : ce qu’on va gagner en puissance machine on va surement le perdre en dev sauf si évidemment l’appli PHP ne bouge jamais ou est compilée à la volée..et la on retombre dans les soucis de puissance.
En C, on passe sa vie a compiler pour tel ou tel proc…
J’aime beaucoup l’idée. Je pense aussi que RoadSend a fait un gros boulot. Jamais essayé en prod pour le moment.
A suivre donc..si un jour Zend s’y colle probablement mais pas avant.
décembre 21st, 2009 at 10 h 56 min
A propos de js et des “micro” optimisations, en terme d’impact, c’est tout à fait négligeable, vraiment.
Pour arriver à mesurer des différences en ms il faut utiliser des object énormes.
Donc à moins de coder comme un pied et surtout de ne pas utiliser de framework, on peut charger la mule – sauf pour les mobiles, en tout cas pour le moment.
Je pense que maintenant on a de super frameworks, ce serait bête d’essayer d’optimiser au niveau micro soi-même.
D’ailleurs les codeurs de Mozilla en on fait l’experience avec bespin – la video est à voir.
Quand à l’impact du langage interprété, oui pourquoi pas, mais franchement les optimisations sont plutôt à faire au niveau du serveur, par exemple utiliser Nginx pour remplacer Apache, utiliser un accélérateur comme varnish, et un cacher comme xcache ( oui c’est mon setup pour magento
)
décembre 22nd, 2009 at 15 h 20 min
Pourquoi pas sur les optims serveurs mais le soucis c’est pas tant le combo httpd/accel/opcode cache à mon sens, c’est plus la logique de l’interprété vs le compilé où on gagne un rapport 1 à 10. Coté JS, les implémentations sont tellement variées dans les browsers qu’il faudrait une lib normative à mon sens, une lib optimise par browser en fait.
décembre 24th, 2009 at 15 h 09 min
sauf erreur de ma part, php 6 embarquera un cache d’opcode en natif
décembre 29th, 2009 at 12 h 00 min
Pour JS, quand on voit V8 de Google Chrome, on se dit que c’est les développeurs des browsers qui sont à la masse.
Et pour PHP, y’a un truc qui s’appelle PHAR, ça peut être une bonne solution : http://www.php.net/manual/en/intro.phar.php
décembre 30th, 2009 at 14 h 14 min
C’est vrai qu’il y a quand même des incohérences, le manque de standardisation est un problème grave également. Tout le monde sais comment interpréter une instruction Javascript, ce qu’un browser doit supporter mais personne n’a mis en place une implémentation standard qui permettent de palier aux problèmes “cross browsers”. C’est pour cela qu’une lib qui détecte le browser et traitent des fonctions différemment selon le navigateur me paraitrait un palliatif efficace. (car, non, je ne compte pas sur les éditeurs de ces navigateurs pour être raisonnables)
Merci pour le tips sur Phar, je vais tester cela.
mars 6th, 2010 at 20 h 53 min
Les gars de chez facebook ils ont sortit un truc dans le genre récement.
ça s’appelle HipHop
http://developers.facebook.com/news.php?blog=1&story=358
Je suis d’accord sur le fond. mais tu imagine la galère s’il fallait recompiler une page php à chaque modification (la plus part des modifications sont mineures en général).
mars 8th, 2010 at 10 h 13 min
En fait je pense que c’est prometteur si on peut détecter les changements. En gros l’idée qu’on poursuit en interne c’est de faire la requête sur le front et sur un compilo en parallèle. Si des changements ont eu lieu et nécessitent la recompilation de la page, alors on rafraichit, sinon on laisse la page présente. Vu le gain de perfs, on peut facilement envisager de faire cette “veille” en continue.
mars 8th, 2010 at 14 h 31 min
Mouais, sauf que PHP n’est plus réellement un langage interprété depuis perpet. C’est bien une compilation en langage intermédiaire avec une simili VM qui exécute ensuite qui se passe. Au final si on passe deux fois sur la même partie de code, on ne réinterprête pas le code.
Ca fait aussi bien longtemps que le code n’est même plus interprété à chaque requête mais qu’on cache l’opcode (c’est dire justement le résultat de cette compilation) via APC ou d’autres. Bref, ne reste que l’exécution dans la VM de PHP.
Bref, vue la fiabilité de l’analyse de l’article, autant ne pas analyser. Quant aux “compilateurs”, il y a eu des essais vers la JVM, vers le CLR, et le HipHop de facebook, à défaut d’être un réel compilateur, permet de faire passer par l’étape C++ pour obtenir bel et bien du code binaire exécutable directement.
Certes PHP n’est pas une foudre de guerre, mais le principal c’est surtout du à l’aspect dynamique, pas tellement à la VM ou au manque de compilation en code binaire. Le typage faible dynamique, ça coute cher, c’est ainsi.
Tout est une question de compromis entre la vitesse de développement et la vitesse d’exécution.
mars 8th, 2010 at 15 h 38 min
les vrais bottlenecks en PHP comme en JS ne sont pas dépendants des langages eux même, il est important de les connaître car lorsqu’on veut optimiser un code, on commence par ce qui prend le plus de temps :
Fais du profiling sur un site un peu complexe, côté PHP ce qui va ressortir le plus souvent, ce sont :
- les accès disque (autoinclude de dizaines de classes, caching, templating … )
- les accès réseau (rapatriement des données de la base, contact d’API externes …)
Et après seulement tu vas commencer à voir les limites du langage dans certains cas précis, par exemple si tu fais beaucoup de templating, tu vas voir les manipulations de string et les regexp qui prennent du temps CPU
Côté browser, c’est la même histoire si l’on fait du profiling :
- le browser passe son temps à attendre des css et des fichiers javascript, pendant ce temps la page est soit blanche soit inaccessible
- chaque inclusion de widget ou plus fréquemment de pub bloque aussi le rendu, le temps d’être retrouvé puis exécuté
- une fois toute la page chargée, ce sont les manipulations dans le DOM qui donnent des coups de freeze (animations, insertions de contenu …)
Et après seulement on tombe sur les limites de JS, la principale étant la manipulation des strings.
Bref, connaître des astuces de manipulations de string en PHP et en JS c’est bien, et il faut les appliquer si ça ne rend pas le code illisible pour les autres, mais c’est illusoire de compter là dessus
en aparté, pour + de background sur HipHop PHP : http://jpv.typepad.com/blog/2010/02/facebook-php-compiler-hiphop-php-les-limites.html
voir en particulier les liens en bas, il y a un bench où HPHP s’en sort bien, mais c’est une solution que l’on peut commencer à utiliser quand on a déjà traité les autres (réseau, disque)
mars 8th, 2010 at 17 h 52 min
Un programme PHP n’est pas autonome, il a besoin d’autre binaire pour s’exécuter, ce qui n’est pas le cas d’un programme compilé. Plusieurs définition de “compilé” existe. J’ai vu la définition suivante donné sur un article :
“PHP 4 introduced the the Zend engine. This engine splits the processing of PHP code into several phases. The first phase parses PHP source code and generates a binary representation of the PHP code known as Zend opcodes. Opcodes are sets of instructions similar to Java bytecodes. These opcodes are stored in memory. The second phase of Zend engine processing consists in executing the generated opcodes.”
Parser le source, générer un binaire puis executer des opcodes… Voyons voir, comme parser un source en C, le compiler et écrire sa représentation binaire puis l’exécuter? Ou presque. Il reste nécessaire d’avoir ce compilo/VM qui s’exécute et certaines opération se répètent. Un binaire se lance en RAM et y reste jusqu’à nouvel ordre. L’assembleur est stocké en mémoire puis parcouru mais pas de relecture ou rechargement. La définition de compilateur est bien de générer un bytecode ou pseudo bytecode (opcode) mais la différence réside dans le fait de le faire régulièrement ou une seul fois dans le cas qui nous occupe.
De la même façon, Java se compile pour être exécuter dans une VM au final. Ma pensé derrière le terme compilé est celle lié à la génération d’un bytecode directement exploitable par la machine, sans intermédiaire. Comme un code C traduit en assembleur. La démarche de HipHop m’intéresse donc à ce titre.
APC réduit effectivement le temps d’exécution mais les process PHP pullulent quand même en mémoire et mangent un sacré paquet de temps CPU.
Quand aux “traducteurs” (injustement assimilé au compilateur dans mon article), oui, ils peuvent aider, en tout cas je le pense même si cela reste une opinion à étayer par un benchmark. Utiliser Hip Hop et Gcc avec un code C++ sera beaucoup plus efficace que de lire et relire le même bout de code en boucle. Par ailleurs les programmes en C/C++ sont beaucoup plus optimisés puisqu’ils tournent de manière très proche du processeur.
La couche VM est consommatrice de ressource par essence et pas forcément utile, si ce n’est pour la portabilité. Mais il vaut mieux avoir un code nativement optimisé pour le processeur. Je suis donc malgré tout confiant dans cet avenir, peut être que les gens de Facebook le sont aussi sinon ils n’auraient pas regardé dans cette direction ne pensez-vous pas ?
Quand au coté “dynamique”, il s’agit juste de réagir différemment en fonction du résultat d’un requête ou de la valeur d’une variable, ce que font aussi les langages compilés depuis bien longtemps. L’opposition n’est pas entre dynamique et compilé mais entre interprété et compilé. Je vous rejoins par contre sur le fait que le typage faible (assistance aux développeurs peu intéressés par les contingences de ressources à mon sens), est un handicape à la performance et à la capacité à en faire un langage compilé.
Je vous rejoins aussi sur le compromis vitesse de dev / vitesse d’exécution. Il s’agit même de ne pas fermer le club des développeurs car peu d’entre eux veulent se frotter à la gestion de la mémoire et au typage fort. Qui n’a jamais hurlé devant un core dump a 3H du matin avec son GDB. Je comprends donc les développeurs qui veulent confier cela à des framework, des interpréteurs ou des garbages collector mais on perd en optimisation.
mars 8th, 2010 at 18 h 06 min
Nous en sommes effectivement à chercher les gains là où il en reste. Une fois les I/O optimisées en activant la concaténation de librairies (mage_compiler pour magento) et en ne gérant que des I/O en RAMdisk, une fois les fooman speedster et autres optimiser de js/css installés, une fois que les reverses proxy prennent en charge les fichiers statiques, une fois os, noyau et hardware optimisé, il nous reste peu d’autres axes d’optimisation. Même les accès réseau se font en Gb/s ce qui est plus rapide qu’un transfert sur disque dur la plupart du temps (quoique les “disques” eux aussi sont réseau sur NAS ou SAN).
Actuellement, nos machines ne swap pas, n’utilise quasi par leurs disques, elles utilisent du CPU. 90% de celui-ci est dédié à PHP, le reste étant du apache et des gestions de requêtes ou de l’OS. Actuellement c’est vraiment les seuls processus qui consomment et ils consomment réellement du CPU, peut importe que l’on ait Zend ou APC.
Merci pour ton post sur typepad au sujet de hip hop.
Déjà, même si l’on ne parle que de 50%, ca vaut le coup ! C’est énorme comme gain. Bon visiblement, ce n’est pas gagné car il y a des limites à prendre en compte, des choses à tester et avant que Zend ou Varien certifie le produit dessus… On peut attendre mais le chemin est le bon je crois.
Quand à Apache, effectivement c’est un fat_boy. Il est temps de composer avec les alternatives et que celles-ci montent en puissance. Le libre a encore des pas à faire dans ce domaine. Zeus est très puissant mais payant et nginx n’est pas encore assez supporté (notamment par Zend), les initiatives fleurissent mais ont du mal à se débarrasser du grand père.
mars 8th, 2010 at 20 h 14 min
Le terme de compilé est peut être maladroit, il est à défaut de mieux, mais il est presque meilleur que “interprété”. Nous ne sommes plus en interprété dans PHP, pas beaucoup plus qu’en Java en tout cas.
Au final ça fait quand même une sacré différence, surtout si la création de l’opcode n’est faite qu’une seule fois.
Mais surtout je m’adresse à ton affirmation sur le fait que les fichiers sont relus et réintéerprétés à chaque exécution. Sauf à se passer de APC, e-accelerator et autres équivalents, ce n’est plus le cas. Et parler performance sans même installer ça serait vraiment étrange.
L’opcode est en mémoire, PHP aussi, les seules “relectures” qui restent ce sont les check de date de fichier au cas où ils ont changé (et même ça c’est désactivable).
Bref, l’état de l’art est bien moins désastreux que ce que ton billet sous-entend.
Après je crains que tu ne surestimes beaucoup l’effet de la compilation. Hip Hop, en réécrivant les interfaces des modules, en transposant en C++ qui compile, ne gagne que 50%. On est loin du rapport 1 à 10 que tu imagines. C’est pour ça que je te parlais de dynamique faiblement typé. Le principe même est complexe, qu’on soit en compilé ou pas.
Après les 50% de Facebook c’est avec des bons développeurs, des systèmes de données dédiés, etc. Pour un site sérieux avec des développeurs pas mauvais le temps pris par les exécutions c’est de l’I/O disque, du SGBDR, des variables d’environnement, des modules tiers bof-bof, etc. Je m’attends à avoir des statistiques bien moins glorieuses sur la plupart des configurations (même pour des développeurs qui se jugent “bons”).
Alors certes on peut retirer le typage faible, trouver un moyen de passer par un compulateur, corriger la liaison entre le serveur web et PHP pour se passer du FastCGI, mais au final on va retrouver les segfault, un confort bien moins grand … quel intérêt de rester avec PHP alors ?
Vu que la force de PHP ce n’est certainement pas sa syntaxe (beurk), ou la cohérence de sa lib standard (beurk x2), autant aller directement sur du C++ ou au moins sur du Java ou du .Net qui ont des VMs qui tournent bien mieux que PHP. Ca fonctionne déjà
Reste après que malheureusement le goulot d’étranglement sur le web ce n’est pas PHP, loin de là. Sur un site classique la page PHP représente moins de 10% du temps de chargement. Optimiser 50% de 10% (donc 5% au final) en tuant tout le confort qui est justement l’avantage de PHP, je ne suis pas convaincu. Ca peut être valable pour certains cas de Facebook mais sinon …
Pour moi ce serait faire l’évolution inverse de toute l’informatique qui a abandonné l’assembleur pour du C, puis abandonné le C pour les langages sur la JVM ou la CLR, et maintenant se penche encore plus sur les langages de scripts comme PHP ruby ou python. Ce n’est pas pour rien, c’est que sauf cas exceptionnels le temps perdu en allant plus près du processeur c’est du temps sur lequel on ne travaille pas l’archi, le réseau, les algos … et qu’au final on ne s’y retrouve pas vraiment.
mars 9th, 2010 at 14 h 43 min
Je ne suis pas sur que tout le code PHP d’un site tournant sous Magento tienne en cache d’opcode dans l’espace RAM réservé pour APC ou autre opcode compiler. Pour rester efficient un cache doit être d’une taille limitée et plus rapide qu’un accès en RAM “classique” aux fichiers PHP eux mêmes.
Ceci dit, 50% ca reste un gain très alléchant. J’espère qu’on pourra faire un solide benchmark prochainement de ces questions.
On a des stats assez différentes visiblement sur ce qui charge les machines. Les I/O disk sont négligeables (all to ram) pour nous, les I/O réseau également, l’OS tiens dans très peu de CPU, nos frontaux sont donc des machines à loop sur de l’apache / mod_php et des opcode optimizers. 90% + du temps CPU en fait.
Sans parler de jeter PHP, visiblement sans trop modifier le langage, on peut arriver à le rendre “compilable”, ce qui déjà est un gain. On va tester mais je pense que ca ira bien au delà des 5% que tu annonce et d’un grand facteur.
Quand au C, il n’est pas en voie d’abandon à mon sens. Avec ses moutures, C++, C#, il reste la composante principale de tous les OS et d’une grande part de l’opensource (qui ne se réduit pas au paradigme LAMP). Ruby, Python et Java ont pu voir le jour car les ressources augmentait et effectivement le ratio temps de dev / vitesse d’execution dont tu parlais a fait basculer vers le développement plus facile. Il y a moyen de ne pas régresser sur les deux plans. Hip hop va dans ce sens. Peut être aurons nous d’ailleurs de nouveaux langages dans quelques années.
Quand au temps passé sur des algos d’optimisation apprenait au moins quelques bases dont tout le monde se fout maintenant. Le C m’a appris à penser à mon code avant de le jeter dans un fichier. Les XSS à profusions que l’on voit, c’était du non controle des entrées dont on se préoccupais bien plus il y a 10 ans pour éviter des buffers overflows. Quand au C++/C#, il reste bien loin du processeur dans sa syntaxe et très proche une fois compilé, mais effectivement, il est fortement typé et il faut gérer ses allocations de RAM, en fait savoir ce que l’on manipule.
Ceci étant, merci de ta participation, c’est un débat et visiblement on est maintenant plus sur des opinions que sur des faits tangibles.
Je t’invite à participer avec nous à un benchmark de tout cela, avec hardware, soft, ingénieurs et tout ce qu’on a en expérience des deux cotés pour fournir des réponses factuelles, scientifiques et statistiques à nos questions sur le domaine et surtout à la communauté.
mars 9th, 2010 at 15 h 58 min
Si tu parles tu cache processeur, non, ça ne tiendra pas. Rien que PHP lui même (le moteur) n’y tiendra pas. Je parle bien d’accès RAM aux opcode plutot qu’aux PHP eux même.
Certes le C n’est pas en disparition lui même, mais côté appli web, on en voit de moins en moins. Ca se limite aux modules/bibliothèques et rarement à l’applicatif.
Après sur les XSS, je désespère à chaque fois que je lis le code de tiers, mais cela tient plus à une culture qu’au langage. Des mauvais développeurs C il y en a aussi et les résultats peuvent être bien plus dramatiques.
“”"Sans parler de jeter PHP, visiblement sans trop modifier le langage, on peut arriver à le rendre “compilable”, ce qui déjà est un gain. On va tester mais je pense que ca ira bien au delà des 5% que tu annonce et d’un grand facteur. “”"
Attention, je ne parle pas de 5% du CPU mais 5% du temps de chargement de la page (images, javascript, html, réseau, tout compris)
mars 9th, 2010 at 16 h 02 min
Evidemment le programme ne tiens pas dans le cache processeur, ni L1, ni L2. Je parle du cache Opcode d’APC ou Zend server.
Ne m’en parle pas. Notre cellule sécurité tombe tous les jours sur des XSS et des SQL injections triviales. C’est dramatique, on en a aussi dans Magento que nous n’avons pas releasé car elles sont en correction chez Varien…