This article does not tell you what an abstract syntax tree is, it needs to be understood, and here is just a description of some of the changes the AST has brought to PHP.
The new execution process
An important change in the PHP7 kernel is the addition of the AST. In PHP5, the process of executing from PHP script to opcodes is:
Lexing: Lexical scan analysis, convert the source file into token flow;
Parsing: parsing, which generates OP arrays at this stage.
Instead of directly generating OP arrays in the parsing phase, Mr. PHP7 is an AST, so the process is one step further:
Lexing: Lexical scan analysis, convert the source file into token flow;
Parsing: parsing, generating abstract syntax tree from token stream;
Compilation: Generates OP arrays from an abstract syntax tree.
Execution time and memory consumption
From the above steps, this is a step ahead of the previous process, so in common sense this will increase the execution time of the program and the use of memory. But in fact the use of memory has actually increased, but the execution time has been reduced.
The following results are tested using small (code about 100 lines), medium (about 700 lines), large (about 2800 rows) of three scripts, test scripts: HTTPS://GIST.GITHUB.COM/NIKIC/289B0C7538B46C2220BC.
100 execution times per file compilation (note that the test results of the article time is 14, PHP7 also called Php-ng time):
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%
Peak Memory in a single compilation:
Php-ng php-ast diff
SMALL 378kB 414kB +9.5%
MEDIUM 507kB 643kB +26.8%
LARGE 1084kB 1857kB +71.3%
The test results for a single compilation may not represent the actual usage, and the following are the results of a complete project test using Phpparser:
Php-ng php-ast diff
Time 25.5ms 22.8ms-11.8%
MEMORY 2360kB 2482kB +5.1%
The tests showed that the program's execution time was generally up to 10% to 15% higher after the AST was used, but memory consumption increased, increasing significantly in a single compilation of large files, but not a serious problem throughout the execution of the project.
Also note that the above results are in the absence of Opcache, the production environment to open the Opcache, the increase in memory consumption is not a big problem.
Semantic changes
If only time optimization, it does not seem to be a sufficient reason to use the AST. In fact, the implementation of the AST is not based on time optimization considerations, but to solve the grammatical problems. Here's a look at some of the semantic changes.
Yield does not require parentheses
In PHP5 implementations, if you use yield in an expression context (for example, on the right side of an assignment expression), you must use parentheses on both sides of the yield declaration:
<?php
$result = yield fn (); Not legal.
$result = (yield fn ()); Legal.
This behavior is only limited by the way the PHP5 is implemented, and in PHP7, parentheses are no longer necessary. So the following are all legal:
<?php
$result = yield;
$result = yield $v;
$result = yield $k => $v;
Of course, you have to follow yield's application scenario.
Parentheses do not affect behavior
In PHP5, ($foo) [' bar '] = ' baz ' and $foo [' bar '] = ' baz ' two statements have different meanings. In fact, the former is illegal, and you get the following error:
<?php
($foo) [' bar '] = ' baz ';
# PHP Parse error:syntax error, unexpected ' [' on line 1
But in PHP7, two ways of writing mean the same thing.
Similarly, if the parameters of the function are wrapped in parentheses, the type check is problematic and the problem is resolved in PHP7:
<?php
function func () {
return [];
}
function ByRef (array & $a) {
}
ByRef ((func ()));
The above code does not alarm in PHP5 unless it is invoked using ByRef (func ()), but in PHP7, no parentheses on either side of Func () will produce the following error:
PHP Strict standards:only variables should is passed by reference ...
The change of list ()
The list keyword behavior has changed a lot. The order in which the list assigns values to variables (the order in which the equals sign is left and right) is previously from right to left and is now Left-to-right:
<?php
List ($array [], $array [], $array []) = [1, 2, 3];
Var_dump ($array);
PHP5: $array = [3, 2, 1]
PHP7: $array = [1, 2, 3]
# Note that the order of the left and right here refers to the same sequence of equals,
# list ($a, $b) = [1, 2] This use of $a = = 1, $b = = 2 is no doubt.
The reason for this change is precisely because in the PHP5 assignment, 3 will be first filled in the array, 1 last, but now the order is changed.
The same changes are also:
<?php
$a = [1, 2];
List ($a, $b) = $a;
PHP5: $a = 1, $b = 2
PHP7: $a = 1, $b = null + "Undefined index 1"
This is because $b gets 2 in the previous assignment, then the value of the $a becomes 1, but now the $a becomes 1, no longer an array, so the $b is null.
List now only accesses each offset once:
<?php
List ($a, $b) = $array;
PHP5:
$b = $array [0][1];
$a = $array [0][0];
PHP7:
Produces an intermediate variable that gets the value of the $array [0]
$_tmp = $array [0];
$a = $_tmp[0];
$b = $_tmp[1];
The empty list members are now all banned, but in some cases previously:
<?php
List () = $a; Not legal
List ($b, list ()) = $a; Not legal
foreach ($a as List ())//PHP5 (not legal in the same way)
Order of reference assignments
The Order of reference assignments is from right to left in the PHP5, now from left to right:
<?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)
}
The __clone method can directly call the
The __clone method can now be invoked directly using the $obj->__clone (). __clone is the only magic method that was previously banned from calling directly, before you get one of these errors:
Fatalerror:cannotcall__clone () methodonobjects-use ' clone $obj ' Insteadin ...
Variable syntax consistency
The AST also solves some grammatical consistency issues that were raised in another RFC: Https://wiki.php.net/rfc/uniform_variable_syntax.
In the new implementation, some of the previous grammatical expressions have a different meaning than they are now, depending on the table below:
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 '] ()
Overall or previous order is from right to left, now from left to right, but also follow the parentheses do not affect the principle of behavior. These complex variable writing is to be paid attention to in the actual development.