Tutoriel: lister les opcodes générés par vos scripts PHP

Icon for post #45

PHP est un langage interprété : les fichiers qui contiennent le code que vous tapez sont parsés par le moteur du langage (le fameux “Zend Engine”), et les instructions qu’ils contiennent sont compilées en des instructions de plus bas niveau, instructions qui seront à leur tour exécutées pour produire le résultat attendu (ou des bugs :P ). Ce processus (code initial => compilation en opcodes => exécution) a lieu à chaque fois que le script est appelé, à moins que vous n’utilisiez un cache d’opcodes qui accélérera l’exécution de vos scripts en faisant sauter des étapes au moteur de PHP…
Maintenant, si vous êtes un maniaque de l’optimisation, ou bien si comme moi vous vous intéressez à tout donc à ce qui se passe “sous le capot de PHP”, vous vous demandez sans doute comment accéder à ces instructions de bas niveau ;)

D’abord, un petit exemple de liste d’opcodes pour vous mettre l’eau à la bouche

1
2
3
4
echo 'Hello, World!';
$first_word = 'This';
$last_word  = 'interesting';
echo $first_word,' is ',$last_word,'!';

…et les opcodes générés d’après ce fichier :

1
2
3
4
5
6
7
8
9
ECHO                  'Hello%2C+World%21'
ASSIGN                !0, 'This'
ASSIGN                !1, 'interesting'
ECHO                  !0
ECHO                  '+is+'
ECHO                  !1
ECHO                  '%21'
RETURN                1
ZEND_HANDLE_EXCEPTION

Je n’entrerai pas dans les détails concernant la signification de ces opcodes, on observe néanmoins que les instructions compilées sont de très bas niveau (”afficher” du texte, “assigner” une valeur à une variable, “afficher” une variable…). En particulier, l’affichage d’une chaîne de caractère comportant 2 variables intercalées (interpolated string en anglais) ne nécessite pas moins de 4 opérations successives! Les tableaux d’opcodes sont donc de très bons amis des optimiseurs fous, qui peuvent repérer quelles portions de leur code pourrait bénéficier d’une accélération substancielle - très substancielle, ne rêvez pas ;)

Comment obtenir de telles listes d’opcodes ?

Les opcodes ne sont pas disponibles directement lorsqu’on appelle un fichier PHP, nous allons donc installer l’extension PHP Vulcain Logic Disassembler qui, utilisée en ligne de commande, va dumper les opcodes générés à partir de vos scripts. Voici comment l’installer et l’utiliser (note: je pars du principe que vous êtes sous Linux, la procédure est certainement différente sous Windows) :

Téléchargez l’archive à cette adresse, et décompressez-là dans un dossier quelquonque. Ouvrez ensuite une console dans ce dossier, et exécutez les commandes suivantes :

1
2
3
user@Computer:~$ phpize
user@Computer:~$ ./configure
user@Computer:~$ sudo make install

Ces commandes vont installer l’extension dans votre environnement ; vous pourrez alors obtenir les opcodes en ligne de commande de cette façon :

1
user@Computer:~$ php -d vld.active=1 -d vld.execute=0 my/very/simple_script.php

Et voilà, vous obtenez un superbe dump d’informations :

user@Computer:~$ php -d vld.active=1 -d vld.execute=0 my/very/simple_script.php
Branch analysis from position: 0
Return found
filename:       my/very/simple_script.php
function name:  (null)
number of ops:  9
compiled vars:  !0 = $first_word, !1 = $last_word
line    #  op                           fetch     ext  return  operands
-------------------------------------------------------------------------------
   2    0  ECHO                                                'Hello%2C+World%21'
   3    1  ASSIGN                                              !0, 'This'
   4    2  ASSIGN                                              !1, 'interesting'
   5    3  ECHO                                                !0
        4  ECHO                                                '+is+'
        5  ECHO                                                !1
        6  ECHO                                                '%21'
   7    7  RETURN                                              1
        8* ZEND_HANDLE_EXCEPTION

Sympa, non ?

Note:vld.active” active ou non l’extension, et “vld.execute” exécute ou non le script.

Quelques liens pour en savoir plus

Je vous recommande les excellents articles de Sara Golemon, notamment celui-ci et celui-là. J’ai redécouvert ce blog tout à l’heure et je m’en suis très fortement inspiré pour cet article (attention, c’est technique et en anglais). Ces articles datent un peu, mais ils sont d’une grande précision et devraient vous aider à mieux comprendre comment fonctionne le bouzin :D

blogasty

Articles Suggérés

Pas de commentaire pour l'instant :-(

Aucun trackback

  1. Loading...

Laisser un commentaire