web-dev-qa-db-ja.com

PHP)での変数展開とsprintfのパフォーマンス

パフォーマンスに関して、以下のことには違いがありますか?

$message = "The request $request has $n errors";

そして

$message = sprintf('The request %s has %d errors', $request, $n);

pHPで?

関数の呼び出しにはもっと多くのことが必要だと思いますが、変数名を展開するために舞台裏でPHPが何をしているのかわかりません。

ありがとう!

24
elitalon

変数についても解析する必要がある二重引用符で囲まれた文字列を指定しているため、すべての場合で2番目の速度は速くなりません。マイクロ最適化を行う場合、適切な方法は次のとおりです。

$message = sprintf('The request %s has %d errors', $request, $n);

それでも、関数呼び出し、文字列の解析、値の変換などのオーバーヘッドのため、秒は遅いと思います(@Pekkaが実際には違いは問題ではないと指摘しました)。ただし、2行のコードはそうではないことに注意してください。 2番目のケースでは$ nが整数に変換されるため、同等です。 $ nが「エラーなし」の場合、最初の行は次のように出力されます。

The request $request has no error errors

2番目のものは出力しますが:

The request $request has 0 errors
28

それは問題ではありません。

パフォーマンスの向上はごくわずかであるため、10000秒または100000回の反復でのみ(数百秒の改善として)表示されます。

具体的な数値については、 このベンチマーク を参照してください。数百ミリ秒で測定可能な差を達成するには、100,000の関数呼び出しを使用して1MB以上のデータを生成する必要があることがわかります。現実の状況はほとんどありません。最も遅いメソッド(「位置パラメータを使用したsprintf()」)でさえ、0.00456ミリ秒しかかかりませんが、最も速いメソッドは0.00282ミリ秒です。 100,000の文字列出力呼び出しを必要とする操作の場合、これを最適化することで節約できる可能性がある100ミリ秒よりも1桁遅い他の要因(ネットワークトラフィックなど)があります。

あなたや他の人にとってあなたのコードを最も読みやすく、維持しやすいものなら何でも使ってください。個人的には、sprintf()メソッドは素晴らしいアイデアです。自分でそれを使い始めることを考えなければなりません。

36
Pekka

「変数展開とsprintf」に関するパフォーマンス分析が行われました ここ

@pekkaが言うように、「あなたのコードをあなたや他の人にとって最も読みやすく、保守しやすいものにします」。パフォーマンスの向上が「低い」(〜2回未満)場合は、無視してください。

ベンチマークの要約:PHPは、二重引用符とヒアドキュメントの解像度に最適化されています。平均時間に関するパーセンテージ、のみを使用して非常に長い文字列を計算する

  • 二重引用の解像度:75%
  • ヒアドキュメントの解像度:82%
  • 一重引用符の連結:93%
  • sprintfフォーマット:117%
  • インデックス付きパラメーターを使用したsprintfフォーマット:133%

Sprintfのみが何らかのフォーマットタスクを実行し(ベンチマークの「%s%s%d%s%f%s」を参照)、@ Darhazerが示すように、出力にいくつかの違いがあることに注意してください。より良いテストは、2つのベンチマークです。1つは連結時間( '%s'フォーマッター)のみを比較し、もう1つはフォーマットプロセスを含みます—たとえば '%3d%2.2f'と、変数を二重引用符に展開する前の同等の機能...短いテンプレート文字列を使用したベンチマークの組み合わせ。

長所と短所

sprintfの主な利点は、ベンチマークで示されているように、非常に低コストのフォーマッター(!)です。一般的なテンプレートについては、 vsprintf 関数の使用をお勧めします。

double-quoted(およびヒアドキュメント)の主な利点は、パフォーマンスです。 sprintfの位置マークと比較した場合、パラメーターの数(1以降)とともに増加する、名目上のプレースホルダーの読みやすさと保守性。

インデックス付きプレースホルダーの使用は、sprintfによる保守性の中間にあります。

注:本当に必要な場合にのみ、一重引用符の連結を使用しないでください。 PHP "Hello {$user}_my_brother!"のような安全な構文、および"Hello {$this->name}!"のような参照を有効にすることを忘れないでください。

21
Peter Krauss

驚いたが、for PHP 7. *「$ variablesreplacement」が最速のアプローチ

$message = "The request {$request} has {$n} errors";

あなたはそれを自分で証明することができます:

$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
        $message = "The request {$request} has {$n} errors";
}
$ctime = microtime(true);
echo '

"variable $replacement timing": '.  ($ctime-$mtime);




$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
        $message = 'The request '.$request.' has '.$n.' errors';
}
$ctime = microtime(true);
echo '

"concatenation" . $timing: '.  ($ctime-$mtime);



$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
        $message = sprintf('The request %s has %d errors', $request, $n);
}
$ctime = microtime(true);
echo '

sprintf("%s", $timing): '.  ($ctime-$mtime);

PHP 7.3.5の結果:

「可変$ replacementタイミング」:0.091434955596924

「連結」。 $タイミング:0.11175799369812

sprintf( "%s"、$ Timing):0.17482495307922

おそらく、「二重引用符で囲まれた変数の代わりにsprintfを使用すると、約10倍高速になる」などの推奨事項がすでに見つかりました。 良いものは何ですかPHPパフォーマンスのヒント?

真実だったと思いますが、ある日。つまり、PHP 5.2。*の前

当時の様子のサンプルを次に示しますPHP 5.1.6

「可変$ replacementタイミング」:0.67681694030762

「連結」。 $タイミング:0.24738907814026

sprintf( "%s"、$ Timing):0.61580610275269

2
Eugene Kaurov

複数の文字列変数を文字列に挿入する場合、最初の変数の方が高速になります。

$message = "The request $request has $n errors";

また、1回の注入の場合、dot(。)の連結が高速になります。

$message = 'The request '.$request.' has 0 errors';

10億ループで反復を行い、違いを見つけます。

例:

<?php

    $request = "XYZ";
    $n = "0";
    $mtime = microtime(true);
    for ($i = 0; $i < 1000000; $i++) {
            $message = "The request {$request} has {$n} errors";
    }
    $ctime = microtime(true);
    echo ($ctime-$mtime);

?>
2
George Mathew

さまざまなベンチマークを見るとわかる単一の変数割り当てのコンテキストを考慮すると、最終的には1番目が最速です。ただし、コアPHP関数のsprintfフレーバーを使用すると、より拡張性の高いコードが可能になり、opcacheやapcなどのバイトコードレベルのキャッシュメカニズムに最適化される可能性があります。言い換えると、特定のサイズのアプリケーションでは、sprintfメソッドを使用するときに使用するコードが少なくて済みます。 RAMにキャッシュする必要のあるコードが少なければ少ないほど、他のものやより多くのスクリプトのためにRAMが多くなります。ただし、これは、スクリプトが評価を使用してRAMに適切に適合しない場合にのみ問題になります。

0
Shapeshifter