php5でインライン文字列を使用する場合と連結を使用する場合の速度の違いは何ですか?
-
08-06-2019 - |
質問
(php5 を想定) 検討してください
<?php
$foo = 'some words';
//case 1
print "these are $foo";
//case 2
print "these are {$foo}";
//case 3
print 'these are ' . $foo;
?>
1と2ではあまり違いはありませんか?
そうでない場合は、1/2 から 3 の間はどうでしょうか。
解決
「実際の生活では何が速いか」に関するすべての質問と同様、現実のテストに勝つことはできません。
function timeFunc($function, $runs)
{
$times = array();
for ($i = 0; $i < $runs; $i++)
{
$time = microtime();
call_user_func($function);
$times[$i] = microtime() - $time;
}
return array_sum($times) / $runs;
}
function Method1()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = "these are $foo";
}
function Method2()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = "these are {$foo}";
}
function Method3()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = "these are " . $foo;
}
print timeFunc('Method1', 10) . "\n";
print timeFunc('Method2', 10) . "\n";
print timeFunc('Method3', 10) . "\n";
数回実行してすべてをページインしてから...
0.0035568
0.0035388
0.0025394
したがって、予想どおり、補間は実質的に同一です (ノイズ レベルの違いは、おそらく補間エンジンが処理する必要がある余分な文字によるものです)。直接連結の速度は約 66% ですが、それほど大きな衝撃ではありません。補間パーサーは検索しても何もすることがなく、単純な内部文字列連結で終了します。たとえ連結が高価だったとしても、補間器はそれを行う必要があります。 後 変数を解析して元の文字列をトリム/コピーするすべての作業です。
Somnath による更新:
上記のリアルタイムロジックに Method4() を追加しました。
function Method4()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = 'these are ' . $foo;
}
print timeFunc('Method4', 10) . "\n";
Results were:
0.0014739
0.0015574
0.0011955
0.001169
文字列のみを宣言しているだけで、その文字列も解析する必要がない場合、PHP デバッガの解析を混同する必要はありません。私の言いたいことを理解していただければ幸いです。
他のヒント
性能差はこんな感じでした 無関係な 少なくとも 2012 年 1 月以降、おそらくそれ以前から:
Single quotes: 0.061846971511841 seconds
Double quotes: 0.061599016189575 seconds
PHP の以前のバージョンには違いがあった可能性があります。私は個人的に二重引用符より一重引用符の方が好きなので、これは便利な違いでした。この記事の結論は次のような素晴らしい点を述べています。
自分で捏造したわけではない統計を決して信用しないでください。
(記事ではこのフレーズが引用されていますが、元の皮肉はおそらく誤ったものでした) 起因する ウィンストン・チャーチルに対して、ヨーゼフ・ゲッペルスの宣伝省がチャーチルを嘘つきとして描くためにでっち上げたものである。
Ich traue keiner Statistik, die ich nicht selbst gefälscht habe.
これは大まかに言い換えると、「私は自分自身を偽っていないという統計を信頼しません」という意味です。)
@Adam のテストが使用されました
"these are " . $foo
以下の方がさらに高速であることに注意してください。
'these are ' . $foo;
これは、二重引用符で囲まれた「文字列」が評価されるのに対し、一重引用符で囲まれた「文字列」はそのまま受け取られるという事実によるものです。
PHP での文字列操作の最適化にあまり夢中にならないでください。連結 vs.データベース クエリの記述が不十分であるか、いかなる種類のキャッシュ スキームも使用していない場合、補間は (実際のパフォーマンスでは) 意味がありません。文字列操作は、後でコードをデバッグしやすく、パフォーマンスの違いが無視できるような方法で記述してください。
@uberfuzzyこれが言語の詳細に関する単なる質問であると仮定すると、問題ないと思います。私は、実際のアプリケーションにおける一重引用符、二重引用符、およびヒアドキュメントのパフォーマンスを比較することは、貧弱なデータベース クエリなどの実際のパフォーマンス シンクと比較すると無意味であるということを会話に追加しようとしているだけです。
実行時間の違いはまったく無視できます。
参照してください
- NikiC のブログ:一重引用符のパフォーマンスに関する神話の反証 PHP で補間と連結がどのように機能するのか、またその速度を気にすることがまったく無意味である理由については、技術的な説明をご覧ください。
このような微細な最適化に時間を無駄にしないでください。プロファイラーを使用して現実世界のシナリオでアプリケーションのパフォーマンスを測定し、実際に必要な箇所を最適化します。単一のずさんな DB クエリを最適化すると、コード全体に微細な最適化を適用するよりもパフォーマンスが大幅に向上する可能性があります。
フォーラム ソフトウェアの開発者である Vanilla が、コード内のすべての二重引用符を一重引用符に置き換えたところ、かなりのパフォーマンスの向上が見られたことを覚えているようです。
ただし、現時点では議論へのリンクを追跡できないようです。
変数を連結すると違いが生じます...そしてその結果に対して何をしているのか...そして、実行していることが出力にダンプしている場合は、出力バッファリングがオンであるかどうかです。
また、サーバーのメモリ状況はどうなっていますか?通常、上位レベルのプラットフォームでのメモリ管理は、下位レベルのプラットフォームのメモリ管理よりも劣ります...
$a = 'parse' . $this;
ユーザーコードプラットフォームレベルでメモリを管理しています...
$a = "parse $this";
PHPシステムコードプラットフォームレベルでメモリを管理しています...
したがって、CPU に関連するこれらのベンチマークはすべてを物語るものではありません。
ベンチマークを 1000 回実行する場合と、同じシミュレーションを同時に 1000 回実行しようとするサーバー上でベンチマークを 1000 回実行する場合...アプリケーションの範囲によっては、大幅に異なる結果が得られる場合があります。
二重引用符を使用すると、処理が大幅に遅くなる可能性があります。いくつかの場所でこれを行う方が良いと読みました
'parse me '.$i.' times'
よりも
"parse me $i times"
ただし、2 番目の方がコードが読みやすいと思います。
二重引用符で囲まれた文字列構文内で変数を使用している場合は、さらに何かを追加します。
$foo = "hello {$bar}";
よりも速いです
$foo = "hello $bar";
そして、これらはどちらもより高速です
$foo = 'hello' . $bar;
実際には全く違いはありません!タイミングを参照してください。 http://micro-optimization.com/single-vs-double-quotes
3 つの変数を使用して Adam Wright による例の修正バージョンを使用すると、結果が逆転し、最初の 2 つの関数が一貫して実際に高速になることに注意してください。これは CLI 上の PHP 7.1 を使用した場合です。
function timeFunc($function, $runs)
{
$times = array();
for ($i = 0; $i < $runs; $i++)
{
$time = microtime();
call_user_func($function);
@$times[$i] = microtime() - $time;
}
return array_sum($times) / $runs;
}
function Method1()
{
$foo = 'some words';
$bar = 'other words';
$bas = 3;
for ($i = 0; $i < 10000; $i++)
$t = "these are $foo, $bar and $bas";
}
function Method2()
{
$foo = 'some words';
$bar = 'other words';
$bas = 3;
for ($i = 0; $i < 10000; $i++)
$t = "these are {$foo}, {$bar} and {$bas}";
}
function Method3()
{
$foo = 'some words';
$bar = 'other words';
$bas = 3;
for ($i = 0; $i < 10000; $i++)
$t = "these are " . $foo . ", " . $bar . " and " .$bas;
}
print timeFunc('Method1', 10) . "\n";
print timeFunc('Method2', 10) . "\n";
print timeFunc('Method3', 10) . "\n";
整数 3 の代わりに「3」でも試してみましたが、同じような結果が得られます。
$bas = 3 の場合:
0.0016254
0.0015719
0.0019806
$bas = '3' の場合:
0.0016495
0.0015608
0.0022755
これらの結果は大きくばらつきがありますが (ばらつきは約 300%)、平均値は比較的安定しているように見え、ほぼ (10 件中 9 件) 常に最初の 2 つのメソッドの方が実行速度が速いことが示されており、メソッド 2 は常に高速であることに注意してください。方法 1 よりわずかに高速です。
結論は:1 つの単一演算 (補間または連結) に当てはまることは、組み合わせた演算には必ずしも当てはまりません。