Maison > Article > développement back-end > Modifications apportées à PHP7 par le nouvel arbre de syntaxe abstraite (AST)
La majeure partie du contenu de cet article est basée sur le document RFC de l'AST : https://wiki.php.net/rfc/abstract_syntax_tree , Des extraits du document source sont introduits pour faciliter la compréhension.
Cet article ne vous dira pas ce qu'est un arbre de syntaxe abstraite. Vous devez le comprendre vous-même. Cet article décrit uniquement certains changements qu'AST apporte à PHP.
Nouveau processus d'exécution
Un changement important dans le cœur de PHP7 est l'ajout d'AST. En PHP5, le processus d'exécution des scripts php en opcodes est :
1. Lexing : analyse lexicale, conversion des fichiers sources en flux de jetons
2. généré à ce stade.
3. En PHP7, les tableaux op ne sont plus directement générés lors de l'étape d'analyse syntaxique, mais AST est généré en premier, il y a donc une étape supplémentaire dans le processus :
4. analyse d'analyse lexicale, conversion du fichier source en flux de jetons
5. Analyse syntaxique, génération d'un arbre de syntaxe abstrait à partir du flux de jetons
6. arbre syntaxique.
Temps d'exécution et consommation de mémoire
D'après les étapes ci-dessus, il s'agit d'une étape de plus que le processus précédent, donc selon le bon sens, cela augmentera l'exécution du programme utilisation du temps et de la mémoire. Mais en fait, l'utilisation de la mémoire a effectivement augmenté, mais le temps d'exécution a diminué.
Les résultats suivants sont obtenus en testant trois scripts : petit (environ 100 lignes de code), moyen (environ 700 lignes) et grand (environ 2800 lignes de script de test : https). ://gist.github.com/nikic/289b0c7538b46c2220bc
Temps d'exécution de la compilation de chaque fichier 100 fois (à noter que le temps de résultat du test de l'article est de 14 ans, PHP7 est aussi appelé PHP-NG ) :
php-ng | php-ast | diff | |
---|---|---|---|
SMALL | 0.180s | 0.160s | -12.5% |
MEDIUM | 1.492s | 1.268s | -17.7% |
LARGE | 6.703s | 5.736s | -16.9% |
Pic de mémoire dans une seule compilation :
|
php-ng | php-ast | diff | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
PETIT | 378 Ko | 414 Ko | +9,5 % | ||||||||||||||||
MOYEN | 507 Ko | 643 ko | +26,8 % | ||||||||||||||||
LARGE | 1 084 ko | 1 857 ko | +71,3%
Les résultats des tests d'une seule compilation peuvent ne pas représenter l'utilisation réelle. Voici les résultats d'un test de projet complet utilisant PhpParser. :
|
php-ng | php-ast | diff | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
TEMPS | 25,5 ms | 22,8 ms | - 11,8% | ||||||||||||
MÉMOIRE | 2360 Ko | 2482 Ko | +5,1% |
Les tests montrent qu'après l'utilisation d'AST, le temps d'exécution global du programme est amélioré d'environ 10 à 15 %, mais la consommation de mémoire augmente également. L'augmentation est évidente dans une seule compilation de fichiers volumineux, mais pas dans la. tout le processus d’exécution du projet. Problème très grave.
Notez également que les résultats ci-dessus sont tous sans Opcache. Lorsque Opcache est activé dans un environnement de production, l'augmentation de la consommation de mémoire n'est pas un gros problème.
Changements sémantiques
S'il ne s'agit que d'une optimisation temporelle, cela ne semble pas être une raison suffisante pour utiliser AST. En fait, la mise en œuvre d’AST ne repose pas sur des considérations d’optimisation du temps, mais sur la résolution de problèmes de syntaxe. Jetons un coup d'œil à quelques changements de sémantique.
yield ne nécessite pas de parenthèses
Dans l'implémentation PHP5, si vous utilisez rendement dans un contexte d'expression (comme sur le côté droit d'une expression d'affectation), vous Vous devez utiliser des parenthèses des deux côtés de la déclaration de rendement :
<?php $result = yield fn(); // 不合法的 $result = (yield fn()); // 合法的
Ce comportement est uniquement dû aux limitations d'implémentation de PHP5. En PHP7, les parenthèses ne sont plus nécessaires. Ainsi les méthodes d'écriture suivantes sont également légales :
<?php $result = yield; $result = yield $v; $result = yield $k => $v;
Bien entendu, vous devez suivre les scénarios d'application du rendement.
Les crochets n'affectent pas le comportement
En PHP5, ($foo)['bar'] = 'baz' et $foo['bar'] = 'baz « Les significations des deux déclarations sont différentes. En fait, l'ancienne façon d'écrire est illégale, et vous obtiendrez l'erreur suivante :
<?php ($foo)['bar'] = 'baz'; # PHP Parse error: Syntax error, unexpected '[' on line 1
Mais en PHP7, les deux façons d'écrire signifient la même chose.
De même, si les paramètres de la fonction sont mis entre parenthèses, il y a un problème avec la vérification de type. Ce problème a également été résolu en PHP7 :
<?php function func() { return []; } function byRef(array &$a) { } byRef((func()));
Le code ci-dessus n'alertera pas. PHP5 à moins que byRef ne soit utilisé (func()), mais en PHP7, qu'il y ait ou non des parenthèses des deux côtés de func(), l'erreur suivante se produira :
PHP Strict standards: Only variables should be passed by reference ...
Changements dans la liste( )
list a beaucoup changé. L'ordre dans lequel la liste attribue des valeurs aux variables (l'ordre à gauche et à droite du signe égal en même temps) était autrefois de droite à gauche, mais maintenant il est de gauche à droite :<?php list($array[], $array[], $array[]) = [1, 2, 3]; var_dump($array); // PHP5: $array = [3, 2, 1] // PHP7: $array = [1, 2, 3] # 注意这里的左右的顺序指的是等号左右同时的顺序, # list($a, $b) = [1, 2] 这种使用中 $a == 1, $b == 2 是没有疑问的。La raison du changement ci-dessus est précisément parce que dans le processus d'affectation de PHP5, 3 seront remplis dans le tableau en premier, 1 en dernier, mais maintenant l'ordre a changé. Les mêmes changements sont :
<?php $a = [1, 2]; list($a, $b) = $a; // PHP5: $a = 1, $b = 2 // PHP7: $a = 1, $b = null + "Undefined index 1"En effet, dans le processus d'affectation précédent, $b a d'abord obtenu 2, puis la valeur de $a est devenue 1, mais maintenant $a change en premier. devient 1 et n'est plus un tableau, donc $b devient nul. La liste n'est désormais accessible qu'une seule fois par offset :
<?php list(list($a, $b)) = $array; // PHP5: $b = $array[0][1]; $a = $array[0][0]; // PHP7: // 会产生一个中间变量,得到 $array[0] 的值 $_tmp = $array[0]; $a = $_tmp[0]; $b = $_tmp[1];Les membres de liste vide sont désormais totalement interdits, auparavant seulement dans certains cas :
<?php list() = $a; // 不合法 list($b, list()) = $a; // 不合法 foreach ($a as list()) // 不合法 (PHP5 中也不合法)
L'ordre de référence assignation
L'ordre d'affectation de référence est de droite à gauche en PHP5, et le présent est de gauche à droite :<?php $obj = new stdClass; $obj->a = &$obj->b; $obj->b = 1; var_dump($obj); // PHP5: object(stdClass)#1 (2) { ["b"] => &int(1) ["a"] => &int(1) } // PHP7: object(stdClass)#1 (2) { ["a"] => &int(1) ["b"] => &int(1) }
__la méthode clone peut appeler directement
Vous pouvez désormais utiliser directement $obj->__clone() pour appeler la méthode __clone. __clone était la seule méthode magique dont il était auparavant interdit d'appeler directement. Auparavant, vous obteniez une erreur comme celle-ci :Fatal error: Cannot call __clone() method on objects - use 'clone $obj' instead in ...
Cohérence de la syntaxe variable
AST a également résolu certaines syntaxes. problèmes de cohérence, ces problèmes ont été soulevés dans une autre RFC :https://wiki.php.net/rfc/uniform_variable_syntax.
Dans la nouvelle implémentation, les significations de certaines expressions grammaticales précédentes sont quelque peu différentes de celles actuelles. Pour plus de détails, veuillez vous référer au tableau suivant :Expression | PHP5 | PHP7 |
---|---|---|
$$foo['bar']['baz'] |
${$foo['bar']['baz']} |
($$foo)['bar']['baz'] |
$foo->$bar['baz'] |
$foo->{$bar['baz']} |
($foo->$bar)['baz'] |
$foo->$bar['baz']() |
$foo->{$bar['baz']}() |
($foo->$bar)['baz']() |
Foo::$bar['baz']() |
Foo::{$bar['baz']}() |
(Foo::$bar)['baz']() |
PHP7"
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!