PHP 7の新しい特性の抽象的な文法の木(AST)の持ってくる変化の詳しい解
5877 ワード
PHP 7の新しい特性の抽象構文ツリー(AST)がもたらす変化を解析した.皆さんの参考にしてください.具体的には以下の通りです.
ここで大部分の内容はASTのRFCドキュメントを参照してください.https://wiki.php.net/rfc/abstractsyntaxtreeを参照してください.
本文はあなたに抽象的な文法の木が何なのかを教えてくれません.これはあなた自身が理解する必要があります.ここではASTがPHPに与えたいくつかの変化を説明するだけです.
新しい実行プロセス
PHP 7のカーネルに重要な変化があるのはASTが入っていることです.PHP 5では、phpスクリプトからopcodesへの実行手順は、次のとおりです. Lexing:語法スキャン分析、ソースファイルをtokenストリームに変換する; Parsing:構文解析、この段階でop arraysを生成します.
PHP 7では文法解析の段階でop arraysを直接生成するのではなく、ASTを先に生成するので、プロセスは一歩増えた. Lexing:語法スキャン分析、ソースファイルをtokenストリームに変換する; Parsing:tokenストリームから抽象構文ツリーを生成する構文解析; Compilation:抽象構文ツリーからop arraysを生成します.
実行時間とメモリ消費量
以上の手順から見ると、これは以前の手順よりも一歩多いので、通常はプログラムの実行時間とメモリの使用が増加します.しかし、実際にはメモリの使用は増加していますが、実行時間は低下しています.
以下の結果は、小(コード約100行)、中(約700行)、大(約2800行)の3つのスクリプトを使用してそれぞれテストされ、スクリプトをテストします.https://gist.github.com/nikic/289b0c7538b46c2220bc.
ファイルごとに100回コンパイルする実行時間(文章のテスト結果に注意する時間は14年、PHP 7が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%
シングルコンパイルのメモリピーク:
php-ng
php-ast
diff
SMALL
378kB
414kB
+9.5%
MEDIUM
507kB
643kB
+26.8%
LARGE
1084kB
1857kB
+71.3%
単一コンパイルのテスト結果は、実際の使用状況を表すものではない場合があります.以下は、PhpParserを使用して完全なプロジェクトテストを行った結果です.
php-ng
php-ast
diff
TIME
25.5ms
22.8ms
-11.8%
MEMORY
2360kB
2482kB
+5.1%
テストにより、ASTを使用した後のプログラムの実行時間は全体的に約10%から15%向上したが、メモリ消費も増加し、大ファイルの単一コンパイルでは明らかに増加したが、プロジェクト全体の実行過程では深刻な問題ではないことが明らかになった.
なお、以上の結果はいずれもOpcacheがない場合、生産環境でOpcacheを開いている場合であり、メモリの消費が増加しても大きな問題ではないことに注意してください.
意味上の変化
時間的な最適化だけであれば、ASTを使う十分な理由でもないようです.実はASTを実現するのは時間の最適化の上の考慮に基づいていないで、文法の上の問題を解決するためです.意味の変化を見てみましょう.
yieldは括弧を必要としません
PHP 5の実装では、1つの式コンテキスト(例えば、付与式の右側)で
このような行為は、PHP 5の実現方式の制限にすぎず、PHP 7では括弧は必須ではなくなっている.次のような書き方も合法的です
もちろん、
かっこは動作に影響しません
PHP 5では、
しかしPHP 7では、両表記は同じ意味を表す.
同様に、関数のパラメータが括弧で囲まれている場合、タイプチェックに問題がある場合、PHP 7でもこの問題は解決されます.
以上のコードはPHP 5では警告されません.
PHP Strict standards: Only variables should be passed by reference ...
List()の変化
リストキーワードの動作がずいぶん変わりました.Listが変数に付与する順序(等号左右同時の順序)は、以前は右から左、現在は左から右:
以上の変化の原因は,PHP 5の付与過程において3が最初に配列に埋め込まれ,1が最後になるためであるが,現在は順序が変化している.
同じ変化は次のとおりです.
これは,以前の付与過程で$bが先に2を得てから$aの値が1になったが,現在では$aが先に1になり,配列ではなくなったため,$bがnullになったからである.
Listでは、オフセットごとに1回しかアクセスできません.
空のlistメンバーは現在すべて禁止されていますが、以前はいくつかの場合にのみ禁止されていました.
参照代入の順序
参照代入の順序はPHP 5では右から左、現在は左から右:
__クローンメソッドは直接呼び出すことができます
Fatal error: Cannot call __clone() method on objects - use 'clone $obj' instead in ...
変数構文の一貫性
ASTもいくつかの文法的整合性の問題を解決した.これらの問題は別のRFCで提案された.https://wiki.php.net/rfc/uniform_variable_syntax.
新しい実装では、以前のいくつかの文法表現の意味は現在とは少し異なり、具体的には以下の表を参照することができます.
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']()
全体的には右から左、今は左から右の順で、カッコが行為に影響しないという原則にも従っています.これらの複雑な変数の書き方は,実際の開発において注意が必要である.
PHPに関する詳細について興味のある読者は、「PHP拡張開発チュートリアル」、「phpオブジェクト向けプログラム設計入門チュートリアル」、「php+mysqlデータベース操作入門チュートリアル」、「PHPネットワークプログラミングテクニック総括」および「php一般データベース操作テクニック要約」を参照してください.
ここで述べたことが皆さんのPHPプログラム設計に役立つことを願っています.
ここで大部分の内容はASTのRFCドキュメントを参照してください.https://wiki.php.net/rfc/abstractsyntaxtreeを参照してください.
本文はあなたに抽象的な文法の木が何なのかを教えてくれません.これはあなた自身が理解する必要があります.ここではASTがPHPに与えたいくつかの変化を説明するだけです.
新しい実行プロセス
PHP 7のカーネルに重要な変化があるのはASTが入っていることです.PHP 5では、phpスクリプトからopcodesへの実行手順は、次のとおりです.
PHP 7では文法解析の段階でop arraysを直接生成するのではなく、ASTを先に生成するので、プロセスは一歩増えた.
実行時間とメモリ消費量
以上の手順から見ると、これは以前の手順よりも一歩多いので、通常はプログラムの実行時間とメモリの使用が増加します.しかし、実際にはメモリの使用は増加していますが、実行時間は低下しています.
以下の結果は、小(コード約100行)、中(約700行)、大(約2800行)の3つのスクリプトを使用してそれぞれテストされ、スクリプトをテストします.https://gist.github.com/nikic/289b0c7538b46c2220bc.
ファイルごとに100回コンパイルする実行時間(文章のテスト結果に注意する時間は14年、PHP 7が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%
シングルコンパイルのメモリピーク:
php-ng
php-ast
diff
SMALL
378kB
414kB
+9.5%
MEDIUM
507kB
643kB
+26.8%
LARGE
1084kB
1857kB
+71.3%
単一コンパイルのテスト結果は、実際の使用状況を表すものではない場合があります.以下は、PhpParserを使用して完全なプロジェクトテストを行った結果です.
php-ng
php-ast
diff
TIME
25.5ms
22.8ms
-11.8%
MEMORY
2360kB
2482kB
+5.1%
テストにより、ASTを使用した後のプログラムの実行時間は全体的に約10%から15%向上したが、メモリ消費も増加し、大ファイルの単一コンパイルでは明らかに増加したが、プロジェクト全体の実行過程では深刻な問題ではないことが明らかになった.
なお、以上の結果はいずれもOpcacheがない場合、生産環境でOpcacheを開いている場合であり、メモリの消費が増加しても大きな問題ではないことに注意してください.
意味上の変化
時間的な最適化だけであれば、ASTを使う十分な理由でもないようです.実はASTを実現するのは時間の最適化の上の考慮に基づいていないで、文法の上の問題を解決するためです.意味の変化を見てみましょう.
yieldは括弧を必要としません
PHP 5の実装では、1つの式コンテキスト(例えば、付与式の右側)で
yield
を使用する場合は、yield
の両側に括弧を使用する必要があります.
このような行為は、PHP 5の実現方式の制限にすぎず、PHP 7では括弧は必須ではなくなっている.次のような書き方も合法的です
$v;
もちろん、
yield
のアプリケーションシーンに従わなければなりません.かっこは動作に影響しません
PHP 5では、
($foo)['bar'] = 'baz'
と$foo['bar'] = 'baz'
の2つの文の意味が異なる.実際、前の書き方は合法的ではありません.次のような間違いが得られます.
しかしPHP 7では、両表記は同じ意味を表す.
同様に、関数のパラメータが括弧で囲まれている場合、タイプチェックに問題がある場合、PHP 7でもこの問題は解決されます.
以上のコードはPHP 5では警告されません.
byRef(func())
で呼び出さない限り、PHP 7ではfunc()
の両側に括弧があるかどうかにかかわらず、以下のエラーが発生します.PHP Strict standards: Only variables should be passed by reference ...
List()の変化
リストキーワードの動作がずいぶん変わりました.Listが変数に付与する順序(等号左右同時の順序)は、以前は右から左、現在は左から右:
以上の変化の原因は,PHP 5の付与過程において3が最初に配列に埋め込まれ,1が最後になるためであるが,現在は順序が変化している.
同じ変化は次のとおりです.
これは,以前の付与過程で$bが先に2を得てから$aの値が1になったが,現在では$aが先に1になり,配列ではなくなったため,$bがnullになったからである.
Listでは、オフセットごとに1回しかアクセスできません.
空のlistメンバーは現在すべて禁止されていますが、以前はいくつかの場合にのみ禁止されていました.
参照代入の順序
参照代入の順序はPHP 5では右から左、現在は左から右:
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)
}
__クローンメソッドは直接呼び出すことができます
$obj->__clone()
の書き方を直接使用して__clone
メソッドを呼び出すことができます.__clone
は、直接呼び出すことが禁止されていた唯一のマジックメソッドで、このようなエラーが発生しました.Fatal error: Cannot call __clone() method on objects - use 'clone $obj' instead in ...
変数構文の一貫性
ASTもいくつかの文法的整合性の問題を解決した.これらの問題は別のRFCで提案された.https://wiki.php.net/rfc/uniform_variable_syntax.
新しい実装では、以前のいくつかの文法表現の意味は現在とは少し異なり、具体的には以下の表を参照することができます.
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']()
全体的には右から左、今は左から右の順で、カッコが行為に影響しないという原則にも従っています.これらの複雑な変数の書き方は,実際の開発において注意が必要である.
PHPに関する詳細について興味のある読者は、「PHP拡張開発チュートリアル」、「phpオブジェクト向けプログラム設計入門チュートリアル」、「php+mysqlデータベース操作入門チュートリアル」、「PHPネットワークプログラミングテクニック総括」および「php一般データベース操作テクニック要約」を参照してください.
ここで述べたことが皆さんのPHPプログラム設計に役立つことを願っています.