Le PHP est un langage de programmation très répandu sur Internet. Mais à bien lire les listes de diffusion qui lui sont consacrées, qu’elles comptent parmi elles des amateurs ou des professionnels, on se rend compte que c’est aussi un langage très mal connu, voire très peu maîtrisé. Et pour cause ! C’est un langage de programmation qui, de par son histoire, a eu des débuts pratiques, sans fondements théoriques. Par conséquent, son apprentissage consiste lui aussi par des essais sans se soucier de son fonctionnement interne. D’où une certaine méconnaissance de ce langage parmi les plus populaires sur Internet. Aujourd’hui, je vous propose de découvrir le fonctionnement du PHP de par la méthode employée pour l’exécution des scripts PHP et de dévoiler la réalité derrière l’un des fondements du langage : le PHP est-il un langage interprété ou un langage compilé ?
Qu’est-ce qu’un langage interprété ?
Un langage informatique se dit interprété lorsque les instructions qui le composent sont décodées les unes après les autres et exécutées aussitôt. Son fonctionnement est le suivant :
- lire l’instruction ;
- exécuter l’instruction ;
- passer à l’instruction suivante et recommencer.
C’est bel et bien instruction par instruction que le programme est exécuté. En réalité, il n’y a aucune traduction du programme depuis le langage informatique en langage machine interprété par l’ordinateur. L’interpréteur fait une interprétation du langage informatique pas à pas. Cela donne l’avantage d’une exécution immédiate, mais aussi d’une certaine lenteur. De plus, de nombreuses erreurs de syntaxe ne sont identifiées que lorsque le programme est exécuté, et non plus tôt, d’où la difficulté d’identifier certains bugs et erreurs.
D’innombrables dialectes du BASIC des années 1970 et 1980 ont été des langages interprétés. Parmi ceux-ci, l’un de mes préférés, le BASIC Microsoft pour Amstrad CPC, parmi l’un des plus puissants de son temps, sur les ordinateurs 8 bits, ou bien encore le GFA Basic sur Atari ST, un excellent BASIC 16 bits.
Qu’est-ce qu’un langage compilé ?
Un langage informatique se dit compilé lorsque les instructions qui le composent sont d’abord traduites par un compilateur depuis le code source vers le langage machine, l’exécution se faisant alors directement par le processeur de la machine dans son langage natif.
L’un des langages de programmation compilés les plus répandus est le langage C. Le C++, très populaire lui aussi, est aussi un langage compilé.
L’un des avantages d’un langage compilé est sa vitesse d’exécution. De plus, la passe de compilation permet d’identifier les erreurs de syntaxe pour les corriger. Parmi les inconvénients est que le programme est compilé pour un processeur donné, voire un système d’exploitation donné, de sorte qu’il n’est pas aisé d’exécuter le même programme compilé sur une autre architecture.
L’évolution des langages compilés
Pour faire face aux divers inconvénients des langages compilés, le Java a introduit la notion de machine virtuelle. Ainsi, le compilateur Java compile un programme vers du byte code d’une machine virtuelle. Ensuite, la machine virtuelle, spécifique à chaque environnement, exécute le programme via un compilateur JIT (Just in Time) qui charge, compile et exécuté chaque morceau de programme byte code en langage machine.
De plus en plus de programmes informatiques reprennent le même principe, comme le Framework .Net de Microsoft.
Le PHP : interprété ou compilé ?
Contrairement à la croyance populaire, le PHP est un langage compilé au vol, se rapprochant vaguement de la notion de compilation JIT du Java. Ceci étant, le PHP n’intègre pas de passe de compilation explicite en byte code, contrairement au Java.
Lorsqu’un visiteur d’un site web réclame l’affichage d’une page dynamique écrite en PHP, voici, en gros, les étapes qui se déroulent :
- le serveur web voit d’après le type MIME du fichier demandé que c’est au PHP de jouer et lui passe la main (via le module intégré au serveur, ou bien via une interface de type FastCGI, CGI, etc.) ;
- le PHP charge le script depuis le système de fichiers ;
- le PHP compile le script chargé ;
- le PHP exécute le script compilé ;
- le PHP rend la main au serveur web (selon le type d’appel par le serveur web : module, FastCGI, CGI, etc.)
La compilation du script depuis le PHP vers le langage machine se fait à chaque requête au serveur.
Caches code PHP
Comme nous venons de le voir à l’instant, le PHP est un langage compilé qui compile un script avant chacune de ses exécutions. Voici beaucoup de temps perdu, sachant que la plupart des scripts PHP ne changent pas entre deux exécutions. On pourrait alors imaginer de faire une compilation une fois, et de la garder en mémoire.C’est exactement ce que font les caches code PHP dont voici une liste non exhaustive (dans le désordre) :
- APC ou Alternative PHP Cache qui devrait être intégré par défaut dans PHP 6 ;
- eAccelerator qui est dérivé du précédent projet Turck MMcache qui n’est plus maintenu ;
- Zend Platform qui est un ensemble liant compilateur spécifique, encodeur de code source et outils additionnels ;
- The ionCube PHP Accelerator est un cache code, des outils additionnels permettent aussi d’encoder les scripts PHP.
Le principe de fonctionnement d’un cache code PHP est le suivant :
- le serveur web voit d’après le type MIME que c’est au PHP de jouer et lui passe la main (via le module intégré au serveur, ou bien via une interface de type FastCGI, CGI, etc.) ;
- le PHP vérifie s’il a déjà une version compilée du script PHP dans son cache :
- si dans le cache et cache à jour, saute à l’étape 4 ;
- sinon, charge le script depuis le système de fichiers ;
- le PHP compile le script chargé ;
- le PHP exécute le script compilé ;
- le PHP rend la main.
Gain de performances
Grâce au cache code, le PHP peut faire l’économie de l’étape de compilation du script entre deux exécutions d’un même script. Selon la taille du script et la machine sur laquelle il tourne, cela fait généralement économiser entre 50 et 250 ms de temps d’exécution de script. L’expérience montre que cela permet de doubler la vitesse d’excution d’un script PHP.
En outre, les caches code PHP mettent à disposition des scripts des fonctions leur permettant d’utiliser la mémoire cache persistante entre deux exécutions de script pour y stocker des données. Un script peut donc y stocker des valeurs qui changent peu entre deux exécutions, mais qui sont longues à calculer. Par exemple, dans le cas d’un forum, la quantité de messages publiés change rarement et n’a pas besoin d’être mise à jour en temps réel. Or, cela implique parfois des calculs lourds au niveau de la base de données. Stocker cette valeur dans une mémoire persistante pour la réutiliser aux prochains affichages permet ainsi de faire gagner un temps précieux. L’expérience montre que l’on peut là encore doubler les performances d’un script en exploitant la mémoire persistante du cache code PHP pour y stocker des données.
Conclusion
Le PHP est donc un langage compilé, mais un langage compilé assez particulier qui gagne à être optimisé. Ainsi, par l’élimination des temps de compilation redondants et l’utilisation de la mémoire persistante pour le stockage des données, un script PHP peut être accéléré d’un facteur quatre. Qu’attendez-vous pour installer un cache code PHP sur votre serveur ?
Billet fort interessant et très instructif, en réalité j’avais toujours cru que PHP était un langage uniquement interprété, il semble d’ailleurs que je ne me soit pas beaucoup trompé car le compilage à chaque exécution se rapproche beaucoup de l’interprétation.
Je vais en tout cas regarder les services de caches dont tu parles, merci beaucoup pour ce billet encore !
@Arnaud Lefort : Il faut en effet avouer que le mécanisme de compilation du PHP est assez particulier, puisqu’il s’agit d’une compilation JIT totalement cachée pour le développeur.
En revanche, ce qui peut mettre la puce à l’oreille, ce sont certaines erreurs de syntaxe qui empêchent des scripts de s’exécuter. Dans le cadre d’un interpréteur, l’erreur ne serait remarquée par le PHP qu’au moment de l’exécution de l’instruction posant problème, et non en début du script.
Enfin, la plupart des langages, même d’apparence interprétés comme le JavaScript, par exemple, sont de plus en plus souvent compilés avant exécution afin de gagner en performances au moment de l’exécution, justement. Au lancement du navigateur Google Chrome, par exemple, l’équipe de développement avait beaucoup insisté sur la performance du code JavaScript qui est compilé avant exécution pour des performances optimales.
Merci pour ce billet très instructif.
Merci beaucoup pour ce billet.
J’ai toujours cru que le PHP etait interpreté.
En plus je suis assez interessé par les caches qui doivent grandement améliorer les perfs.
Quitte à rectifier des lieux communs, autant le faire en entier. Comme vous le reconnaissez vous-même, les langages interprétés à proprement parler n’existent plus vraiment. Au final, vos catégories « langages compilés »/« langages interprétés » ne représentent plus grand chose.
Et pour cause : un langage n’est pas défini par une implémentation. C’est un objet formel, indépendant de tout compilateur/interpréteur/machine virtuelle.
En outre, il existe depuis longtemps des compilateurs pour PHP, et on en développe de nouveau (Facebook par exemple, avec son HipHop). En fait, j’ai du mal à penser à un langage, à part peut-être C++, pour lequel il n’existe pas à la fois un interpréteur ET un compilateur.
Donc cette distinction n’est pas la bonne, et c’est là-dessus que votre article aurait du porter : les langages « interprétés » ne désignent rien de précis, mais les « langages compilés » non plus. Et PHP n’est ni l’un, ni l’autre.
En revanche, ça continue d’avoir du sens de parler de langage dynamique ou statique (quitte à restreindre son discours à quelques caractéristiques du langage). Voilà le gouffre béant entre C/C++/OCaml/Java/… et Python/PHP/JavaScript.
comme langage web j’aime bien le php pour sa simplicité et pour sa performance (vitesse d’exécution, cache,MVC)
Hello,
très intéressant, merci pour ce poste.
le Phalcon (framework) permet d’optimiser les ressources vu qu’il es développé en C.