つい最近、PHP 関係者が依然として一重引用符と二重引用符について話しており、一重引用符の使用は単なる微細な最適化であるが、常に一重引用符を使用することに慣れていれば、大量のコストを節約できると再び聞きました。 CPU サイクル!
「すべてはすでに言われていますが、まだ誰もが言っていません」 – Karl Valentin
この精神で、ニキータ・ポポフがすでに12年前に書いたのと同じテーマについて記事を書いています(彼の記事を読んでいる場合は、ここで読むのをやめてください)
PHP は文字列補間を実行し、文字列内で使用されている変数を検索し、使用されている変数の値に置き換えます。
この機能は、二重引用符で囲まれた文字列およびヒアドキュメントに限定されています。一重引用符 (または nowdoc) を使用すると、別の結果が得られます:
これを見てください: PHP はその一重引用符で囲まれた文字列内の変数を検索しません。したがって、どこでも一重引用符を使用し始めることができます。そこで人々はこのような変更を提案し始めました ..
.. なぜなら、PHP は一重引用符で囲まれた文字列内の変数を検索しないため (いずれにせよ、この例には存在しません)、より高速になり、そのコードを実行するたびに大量の CPU サイクルを節約できるからです。そして誰もが幸せになり、事件は解決しました。
一重引用符と二重引用符の使用には明らかに違いがありますが、何が起こっているのかを理解するには、もう少し深く掘り下げる必要があります。
PHP はインタープリター型言語ですが、仮想マシンが実際に実行できるもの (オペコード) を取得するために特定の部分が連携するコンパイル ステップを使用しています。では、PHP ソース コードからオペコードにどうやってアクセスするのでしょうか?
レクサーはソース コード ファイルをスキャンし、トークンに分割します。これが何を意味するのかについての簡単な例は、token_get_all() 関数のドキュメントに記載されています。
リーリーこの 3v4l.org スニペットで実際の動作を確認し、試してみることができます。
パーサーはこれらのトークンを受け取り、そこから抽象構文ツリーを生成します。上記の例の AST 表現を JSON として表すと次のようになります:
これも試して、他のコードの AST がどのように見えるかを確認したい場合は、Ryan Chandler による https://phpast.com/ と https://php-ast-viewer.com/ を見つけました。どちらも、特定の PHP コード部分の AST を示します。
コンパイラはASTを取得してオペコードを作成します。オペコードは仮想マシンが実行するものであり、OPcache を設定して有効にしている場合 (これを強くお勧めします)、OPcache に保存されるものでもあります。
オペコードを表示するには、複数のオプションがあります (おそらくもっとあるかもしれませんが、私はこれら 3 つを知っています):
一重引用符と二重引用符を使用するときに CPU サイクルを節約するという最初のアイデアに戻ると、これが成り立つのは、PHP が単一のリクエストごとに実行時にこれらの文字列を評価する場合に限られるということに誰もが同意すると思います。# #
実行時に何が起こるのでしょうか? それでは、PHP が 2 つの異なるバージョンに対してどのオペコードを作成するかを見てみましょう。 二重引用符:
リーリー リーリー
リーリー リーリー
リーリー
リーリー
リーリー
T_OPEN_TAG (ログイン後にコピー
Look at the last two tokens! String interpolation is handled in the lexer and as such is a compile time thing and has nothing to do with runtime.
For completeness, let's have a look at the opcodes generated by this (after optimisation, using 0x20000):
0000 ASSIGN CV0($juice) string("apple") 0001 T2 = FAST_CONCAT string("juice: ") CV0($juice) 0002 ECHO T2 0003 RETURN int(1)
This is different opcode than we had in our simple
Let's have a look at these three different versions:
ログイン後にコピー
The first opcode assigns the string "apple" to the variable $juice:
0000 ASSIGN CV0($juice) string("apple")
The first version (string interpolation) is using a rope as the underlying data structure, which is optimised to do as little string copies as possible.
0001 T2 = ROPE_INIT 4 string("juice: ") 0002 T2 = ROPE_ADD 1 T2 CV0($juice) 0003 T2 = ROPE_ADD 2 T2 string(" ") 0004 T1 = ROPE_END 3 T2 CV0($juice) 0005 ECHO T1
The second version is the most memory effective as it does not create an intermediate string representation. Instead it does multiple calls to ECHO which is a blocking call from an I/O perspective so depending on your use case this might be a downside.
0006 ECHO string("juice: ") 0007 ECHO CV0($juice) 0008 ECHO string(" ") 0009 ECHO CV0($juice)
The third version uses CONCAT/FAST_CONCAT to create an intermediate string representation and as such might use more memory than the rope version.
0010 T1 = CONCAT string("juice: ") CV0($juice) 0011 T2 = FAST_CONCAT T1 string(" ") 0012 T1 = CONCAT T2 CV0($juice) 0013 ECHO T1
So ... what is the right thing to do here and why is it string interpolation?
String interpolation uses either a FAST_CONCAT in the case of echo "juice: $juice"; or highly optimised ROPE_* opcodes in the case of echo "juice: $juice $juice";, but most important it communicates the intent clearly and none of this has been bottle neck in any of the PHP applications I have worked with so far, so none of this actually matters.
String interpolation is a compile time thing. Granted, without OPcache the lexer will have to check for variables used in double quoted strings on every request, even if there aren't any, waisting CPU cycles, but honestly: The problem is not the double quoted strings, but not using OPcache!
However, there is one caveat: PHP up to 4 (and I believe even including 5.0 and maybe even 5.1, I don't know) did string interpolation at runtime, so using these versions ... hmm, I guess if anyone really still uses PHP 5, the same as above applies: The problem is not the double quoted strings, but the use of an outdated PHP version.
Update to the latest PHP version, enable OPcache and live happily ever after!
以上が二重引用符が多すぎるかどうか、それが問題です。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。