新しい抽象構文ツリー (AST) によって PHP7 に加えられた変更

Guanhui
リリース: 2023-02-17 15:06:01
転載
2913 人が閲覧しました

新しい抽象構文ツリー (AST) によって PHP7 に加えられた変更

この記事の内容の大部分は、AST の RFC ドキュメントに基づいています: https://wiki.php.net/rfc/abstract_syntax_tree , 理解を容易にするために、ソース文書からの抜粋が紹介されています。

この記事では、抽象構文ツリーが何であるかについては説明しません。これは自分で理解する必要があります。この記事では、AST が PHP にもたらすいくつかの変更についてのみ説明します。

新しい実行プロセス

PHP7 のコアにおける重要な変更は、AST の追加です。 PHP5 では、PHP スクリプトからオペコードまでの実行プロセスは次のとおりです:

1. 字句解析: 字句スキャン分析、ソース ファイルをトークン ストリームに変換します;

2. 解析: 構文分析、Op 配列はこの段階で生成されます。

3. PHP7 では、op 配列は構文分析段階で直接生成されなくなりましたが、AST が最初に生成されるため、プロセスにはもう 1 つのステップがあります:

4. 字句解析:字句スキャン分析、ソース ファイルをトークン ストリームに変換;

5. 解析: 構文分析、トークン ストリームから抽象構文ツリーを生成;

6. コンパイル: 抽象から op 配列を生成構文ツリー。

実行時間とメモリ消費量

上記の手順から、これは前のプロセスよりも 1 つの手順が多いため、常識的には、これによりプログラムの実行時間が増加します。時間とメモリの使用量。しかし実際には、メモリ使用量は確かに増加していますが、実行時間は減少しています。

次の結果は、小規模 (約 100 行のコード)、中規模 (約 700 行)、および大規模 (約 2800 行) の 3 つのスクリプトをテストして得られます。テスト スクリプト: https ://gist.github.com/nikic/289b0c7538b46c2220bc

各ファイルを 100 回コンパイルする実行時間 (記事のテスト結果時間は 14 年であることに注意してください、PHP7 とも呼ばれます) PHP-NG ):

#SMALL0.180s0.160s-12.5%MEDIUM1.492s1.268s-17.7%LARGE6.703s 5.736s-16.9%1 回のコンパイルでのメモリ ピーク:

##php-ng
php-ast diff


#php-ng##SMALL378kB414kB 9.5%643kB1857kB単一コンパイルのテスト結果は、実際の使用状況を表していない可能性があります。以下は、PhpParser を使用した完全なプロジェクト テストの結果です:

php-ast
diff
##MEDIUM 507kB
26.8% 1084kB
71.3%

##php-ngphp-ast 時間25.5ms22.8ms-11.8% 5.1%##

テストによると、AST を使用した後、プログラムの全体的な実行時間は約 10% ~ 15% 改善されましたが、メモリ消費量も増加しました。この増加は、大きなファイルの 1 回のコンパイルでは明らかですが、実行中はそうではありません。プロジェクトの実行プロセス全体が非常に深刻な問題です。

また、上記の結果はすべて Opcache を使用していないことにも注意してください。運用環境で Opcache がオンになっている場合、メモリ消費量の増加は大きな問題ではありません。

セマンティックな変更

これが単なる時間の最適化である場合、AST を使用する十分な理由にはならないようです。実際、AST の実装は時間の最適化を考慮したものではなく、構文の問題を解決するために行われています。セマンティクスにおけるいくつかの変更を見てみましょう。

yield には括弧は必要ありません

PHP5 実装では、式コンテキスト (代入式の右側など) で yield を使用する場合、 yield 宣言の両側で括弧を使用する必要があります:

ログイン後にコピー

この動作は、PHP5 の実装制限によるものです。PHP7 では、括弧は必要なくなりました。したがって、次の記述方法も合法です:

 $v;
ログイン後にコピー

もちろん、yield のアプリケーション シナリオに従わなければなりません。

括弧は動作に影響しません

PHP5 では、($foo)['bar'] = 'baz' および $foo['bar'] = 'baz ' 2 つのステートメントの意味は異なります。実は、前者の書き方は違法であり、次のようなエラーが発生します。

ログイン後にコピー

しかし、PHP7 では、2 つの書き方は同じ意味になります。

同様に、関数のパラメータが括弧で囲まれている場合、型チェックに問題があります。この問題は PHP7 でも解決されています:

ログイン後にコピー

上記のコードは、次の場合には警告しません。 PHP5 では byRef が使用されていない限り (func())、PHP7 では func() の両側に括弧があるかどうかに関係なく、次のエラーが発生します。

PHP Strict standards: Only variables should be passed by reference ...
ログイン後にコピー

Changes in list()

list キーワードの動作が大幅に変更されました。リストが変数に値を割り当てる順序 (等号の左右の順序) は、以前は右から左でしたが、現在は左から右です:

ログイン後にコピー

上記の変更の理由は、正確には、PHP5 の代入プロセスでは、最初に 3 が配列に入力され、最後に 1 が入力されるためですが、順序が変更されたためです。

同じ変更は次のとおりです:

ログイン後にコピー

これは、前の代入プロセスで $b が最初に 2 を取得し、その後 $a の値が 1 になったためです。しかし、今回は $a が最初に変更されます。は 1 になり、配列ではなくなるため、$b は null になります。

list はオフセットごとに 1 回のみアクセスされるようになりました:

ログイン後にコピー

以前は特定の状況下でのみ空のリスト メンバーがすべて禁止されました:

ログイン後にコピー

参照の順序assign

参照割り当ての順序は、PHP5 では右から左でしたが、現在は左から右です。

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)
}
ログイン後にコピー

#clone メソッドは直接呼び出し可能です

これで、$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.

新しい実装では、以前の文法表現の意味は現在とは多少異なります。詳細については、次の表を参照してください:

diff
##メモリ 2360kB 2482kB
##$foo->{$bar['baz']} ##$foo->$ bar['baz' ]()推奨チュートリアル:「PHP7
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']() 全体的に、以前の順序は右から左でしたが、現在は左から右です。また、括弧は動作に影響を与えないという原則に従います。このような複雑な変数の書き方は、実際の開発では注意が必要です。

以上が新しい抽象構文ツリー (AST) によって PHP7 に加えられた変更の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!