Optimiseur de sources PHP

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

23 déc. 2006, 01:11

Je songe à écrire un script qui analyserait des sources PHP et les "optimiserait". On pourrait par exemple retirer tous les espaces, tabulations, etc... ça ne fait pas gagner en vitesse, mais ça a certains avatanges dans certains cas (assez rare, je le concède). On peut aussi remplacer les longues chaînes entre guillemets et contenant des variables PHP par des chaînes statiques entre apostrophes concaténées avec les variables PHP. (à l'heure actuelle ça devrait être plus rapide)

Avec un peu de boulot, on doit pouvoir identifier certains blocs "if" qui ne s'exécutent pas, ou remplacer certaines constantes par leur valeur, etc... si ça intéresse quelqu'un, vous pouvez répondre dans ce topic. Deux choses :
  • le gain de performance est infinitésimal
  • c'est hyper pas facile à programmer et très ennuyeux
Si malgré tout ça vous avez envie de participer vous serez le bienvenu :)

ViPHP
ViPHP | 3607 Messages

29 déc. 2006, 12:58

moi je serai assez pour ... sachant que je n'aurai pas forcément énormément de temps pour coder, mais si de temps à autre, je peux poser une pierre sur l'édifice, pourquoi pas ;-)
As-tu déja commencé quelquechose? ou tout est à faire ?

ViPHP
ViPHP | 3607 Messages

29 déc. 2006, 14:46

bon alors j'ai commencer à coder sans attendre ta réponse...
voilà ce que j'ai pour l'instant:
le fichier à aoptimiser.php:
<?
$var="iuhig";
echo "blapoih $var ifhj";
?>
et le fichier de traitement:
<?php
function optimiser($content){
    preg_match('#(\"(.*)\")#s', $content, $tab);
    print_r($tab);
	if(isset($tab[2])){
		$var= preg_replace('#(\$([a-z])*)#','\'.$1.\'',$tab[2]);
	}
	if(isset($var)){
		$content=preg_replace('#\"(.*)\"#s','\''.$var.'\'',$content);
	}
    $content=preg_replace('#<\?(.*)\?>#sU','<?php$1?>',$content);
    return $content;
}

$string=file_get_contents('./aoptimiser.php');
$res=optimiser($string);

echo '<h1>Code de départ</h1><pre>'.htmlentities($string).'</pre>';


echo '<h1>Code après optimisation</h1><pre>'.htmlentities($res).'</pre>';
?>
mais ça ne me donne pas tout à fait ce que je souhaite, car le premier preg_match récupère ceci:

Code : Tout sélectionner

Array ( [0] => "iuhig"; echo "blapoih $var ifhj" [1] => "iuhig"; echo "blapoih $var ifhj" [2] => iuhig"; echo "blapoih $var ifhj )
alors qu'il me faudrait quelquechose comme ceci:

Code : Tout sélectionner

Array ( [0] => "iuhig" [1] => "blapoih $var ifhj" )
en gros il prend le premier " et le dernier " et au milieu, il s'en ****, comment lui dire (à la pcre) de prendre tout ce qui est entouré de guillemets, mais qui n'en contient pas (et pour plus tard sauf si il est précédé d'un \)
voilà pour le premier jet!

ViPHP
ViPHP | 3607 Messages

29 déc. 2006, 17:13

voilà j'ai la version finale :) (enfin elle ne fait que remplacer les shorts tag et mettre des guillemets simple à la place des doubles ^^'
<?php
function optimiser($content){
    $content=preg_replace('#"(.+)"#','\'$1\'',$content);
    $content=preg_replace('#(\'.*)(\$[a-z]+)(.*\')#s', '$1\'.$2.\'$3', $content);
    $content=preg_replace('#<\?(.*)\?>#sU','<?php$1?>',$content);
    return $content;
}

$string=file_get_contents('./aoptimiser.php');
$res=optimiser($string);

echo '<h1>Code de départ</h1><pre>'.htmlentities($string).'</pre>';


echo '<h1>Code après optimisation</h1><pre>'.htmlentities($res).'</pre>';
?>
voila ça fonctionne pour mes premiers tests..., faut en faire d'autres bien entendu :)

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

29 déc. 2006, 17:24

Je me demande si tu codes ne va pas bloquer sur un code de cette trempe :
<html>
  <tr>
    <td><?= $mavar ?></td>
  </tr>
</html>
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 3607 Messages

29 déc. 2006, 17:31

houla mais si pour l'instant ça va bloquer c'est sur, mais comme dis plus haut, pour l'instant je fait que remplacer <?...?> par <?php ... ?> et les doubles quotes par des simples.... (et encore, je m'aperçoit que ça foire... :-() par exemple avec cette fonction:
function optimiser($content){
    //$content=preg_replace('#\"(.*)\"#','\'$1\'',$content);
    $content=preg_replace('#"(.+)"#','\'$1\'',$content);
    $content=preg_replace('#(\'.*)(\$[a-z]+)(.*\')#s', '$1\'.$2.\'$3', $content);
    $content=preg_replace('#<\?([^php].*)\?>#sU','<?php$1?>',$content);
    return $content;
}
pour
<?
$var="iuhig";
echo "blapoih $var ifhj";
?>
j'obtient
<?php
$var='iuhig';
echo 'blapoih '.$var.' ifhj';
?>
c'est parfait, mais pour
<?
$var="iuhig";
echo "blapoih $var ifhj";
?>
<html>
<?php
$aih='uig$iyhg';
print ("ojq".$aih."oi");
?>
j'obtient ceci:
<?php
$var='iuhig';
echo 'blapoih $var ifhj';
?>
<html>
<?php
$aih='uig$iyhg';
print ('ojq".'.$aih.'."oi');
?>
et là ça va plus du tout...
pour ce qu'il y a à l'intèrieur du print, je comprend que ça puisse planter, mais je comprend pas pourquoi il change pas comme il faut la première partie du fichier qui identique au premier :-k

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

29 déc. 2006, 18:13

Pour info, j'ai commencé à y travailler et je pense ouvrir un projet chez SourceForge pour l'héberger.

Le truc doit nécessairement être basé sur le tokenizer de PHP pour garantir la validité des optimisations. Il fonctionne en plusieurs passes, voici ce que j'ai terminé pour l'instant:
  • suppression des commentaires et whitespace
  • remplacement des HEREDOC par de vraies chaînes, remplacement des chaînes en guillemets contenant des variables par des chaînes en apostrophes avec concaténation des variables
  • réparation de diverses choses, comme les faux échappements dans les chaînes (eg "\w" est remplacé par '\\w'), ou l'utilisation de l'écriture "alternative" des structures de contrôle ("if (1): endif;")
  • Constant folding
  • Dead code elimination (seulement après "return" ou "exit" pour l'instant)
J'espère pouvoir implémenter d'autres trucs à moyen/long terme comme la propagation des constantes ou améliorer le côté "unreachable code". Pis remplacer concaténer les echo quand c'est possible aussi. À terme, j'aimerais pouvoir transformer
$a = strtolower($b);
$c = strtolower($a);
en
$a = $c = strtolower($b);
C'est un projet à long terme à priori.

ViPHP
ViPHP | 3607 Messages

29 déc. 2006, 20:32

Une petite question, c'est quoi le tokenizer ?
bon alors d'après ce que j'ai compris, j'ai fait un peu de travail pour pas grand chose :langue: , alors pour la suite comment fait on ? on attend que la bête soit sur sourceforge ?
et on avisera les méthodes de collaboration à partir de là ?

Mammouth du PHP | 1885 Messages

29 déc. 2006, 20:41

PHP sépare tout le code en tokens pour analyse.
Tu peux avoir bien du plaisir avec cette fonction: token_get_all()
La programmation est l'expression de la poésie d'un programmeur
Génération PHP

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

29 déc. 2006, 20:59

bon alors d'après ce que j'ai compris, j'ai fait un peu de travail pour pas grand chose :langue:
On ne code jamais pour rien, t'as même appris ce qu'était le tokenizer :P Sinon pour le reste, le mieux est d'attendre d'avoir le script en main (extrêmement mal documenté à l'heure actuelle) mais si tu n'as que peu de temps tu risques de le perdre principalement à comprendre comment les choses fonctionnent. Comme je disais, ça demande beaucoup d'efforts pour pas grand-chose.

Pour info, lorsque j'aurai terminé l'optimiseur d'echo, la transformation de
<?
$var="iuhig";
echo "blapoih $var ifhj";
?>
devrait ressembler à:
<?php $var='iuhig';?>blapoih <?php echo $var;?> ifhj
...puis (constant folding)
<?php $var='iuhig';?>blapoih iuhig ifhj
...et ultimement
blapoih iuhig ifhj
...si $var n'est plus référencé par la suite.

Ce dernier point est débattable dans la mesure où le script en question pourrait être chargé via include() et la variable référencée dans le script parent.

Eléphant du PHP | 78 Messages

29 déc. 2006, 21:13

Pour moi j'ai déja un type de ce projet en cours, mais il est actuellement sur papier et diffère quand même.

Pour ma part
<?
$var="iuhig";
echo "blapoih $var ifhj";
?> 
Devient
<?
$var= 'iuhig';
echo 'blapoih '.$var.' ifhj';
?> 
Cordialement,
winni

ViPHP
ViPHP | 3607 Messages

29 déc. 2006, 21:35

bon alors d'après ce que j'ai compris, j'ai fait un peu de travail pour pas grand chose :langue:
On ne code jamais pour rien, t'as même appris ce qu'était le tokenizer :P
Que je n'ai pas bien compris d'ailleurs :langue:
Sinon pour le reste, le mieux est d'attendre d'avoir le script en main (extrêmement mal documenté à l'heure actuelle) mais si tu n'as que peu de temps tu risques de le perdre principalement à comprendre comment les choses fonctionnent. Comme je disais, ça demande beaucoup d'efforts pour pas grand-chose.
J'attend de voir les fichiers, et de voir si la compréhension est très très très difficile ou juste difficile... et quand je dis peu de temps, ça veut dire 2 à 4 h par semaine, c'est déja raisonnable je pense pour aider :) (au pire je me rabaisserai au poste de bête-testeur ;-)

Eléphant du PHP | 445 Messages

01 janv. 2007, 15:39

Même si ce n'est pas grand chose, as-tu pensé à remplacer les fonctions rand() par des mt_rand() ?

Il me semble avoir lu qu'elle était plus rapide (un chiffre assez important d'ailleurs) dans le bouquin de Cyruss ^^

Sinon, projet très intéressant, mais je n'ai pas encore le niveau pour apporter quoi que ce soit d'utile je pense, donc bonnes chances à ceux qui y participent :)
LLDC
Ulti

ViPHP
ViPHP | 5924 Messages

18 mai 2007, 14:36

J'attend de voir les fichiers, et de voir si la compréhension est très très très difficile ou juste difficile... et quand je dis peu de temps, ça veut dire 2 à 4 h par semaine, c'est déja raisonnable je pense pour aider :) (au pire je me rabaisserai au poste de bête-testeur ;-)
Idem. C'est un projet intéressant mais je ne sais pas si j'aurais la trempe et le temps pour aider vraiment, mais je peux peut être tout de même aider un peu si c'est nécessaire...
Mais par contre, comme disait jojolapine, où ca en est ?

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

18 mai 2007, 16:31

D'ailleurs tiens puisque le sujet revient d'outre-tombe, pour tout ce qui est constant folding & cie je comprends, mais supprimer les commentaires et les whitespaces, est-ce que ça n'a pas fondamentalement aucun intérêt vu que les scripts sont "pré-compilés en mémoire" (et donc certainement que les commentaires & whitespaces n'ont d'influence qu'au premier chargement) ?
Et comment tu vas gérer les commentaires phpdoc qui sont parfois très importants pour le runtime (une librairie comme ezpdo par exemple les utilise activement) ?