1

各反復で大量のテキストを取得し、特定のプレースホルダー (「トークン」) を次のような他のコンテンツに置き換えるループがあります。

$string = $pageContent;
foreach($categories as $row) {
    $images = $mdlGallery->getByCategory($row['id']);
    if (!empty($images)) {
        $plug = Plugin::get('includes/gallery', array('rows' => $images));
        $string = str_replace($row['token'], $plug, $string);
    }
}

Plugin クラスとその get() メソッドは、特定のディレクトリから適切なファイルを取得し、バッファを文字列として出力するだけです。

多数のカテゴリが存在する可能性があるため、次のように strpos() 関数を使用して特定のカテゴリからすべての画像を入力する前に、特定の「トークン」の出現について入力文字列を最初に確認する方がよいかどうか疑問に思います。

foreach($categories as $row) {
    if (strpos($string, $row['token']) !== false) {
        $images = $mdlGallery->getByCategory($row['id']);
        if (!empty($images)) {
            $plug = Plugin::get('includes/gallery', array('rows' => $images));
            $string = str_replace($row['token'], $plug, $string);
        }
    }
}

私の懸念はパフォーマンスです-これは役に立ちますか? - $string には潜在的に多数の文字 (MySQL の TEXT フィールド タイプ) が含まれると考えられますか?

4

3 に答える 3

4

問題を解決するには

サンプルコードによると、使用されているファイルPlugin::get()のサイズが小さいようです。つまり、ファイルを含めたり読み取ったりしても大きなパフォーマンスコストが発生することはありませんが、ファイルが多数ある場合は、OS キューイングメカニズムのためにそれらのコストを考慮する必要がある場合があります。それらに含まれるデータが大きくなくても。

このgetByCategoryメソッドは、データベースへの多くの接続->クエリ->読み取り->クローズ通信シーケンスを意味し、それぞれが大量のデータ(TEXTあなたが言及したフィールド)の転送を意味するため、大きなパフォーマンスコストが発生するはずです。

単一の SQL クエリを使用してデータをバッチ操作としてフェッチし、行 ID でインデックス付けされたキャッシュ変数に格納して、キャッシュからデータをフェッチできるようにすることを検討する必要がありますgetByCategory

現在の問題は単純なコード レビューの問題ではなく、アプローチの問題です。大規模なデータセットを処理するアプローチとして、小規模なデータセットの典型的な手法を使用しました。「単純なスクリプトに foreach をラップする」という概念は、中規模のデータセットがあり、パフォーマンスの低下を感じない場合に機能します。大規模なデータセットを処理するための別のアプローチが必要ない場合です。

あなたの質問に答えるために

使用strposとは、干し草の山全体を一度実行して針が含まれているかどうかを確認し、その後もう一度実行して で置換することを意味しstr_replaceます。

干し草の山に針が含まれていない場合strpos === str_replace(計算の複雑さの問題で)、針が存在しないことを確認するために、両方とも文字列全体を最後まで実行する必要があるためです。

両方の関数を使用すると、針を含まない干し草の山では計算の複雑さが 100% 増加し、針を含む干し草の山では計算の複雑さが 1% から 100% 増加しますstrpos。これは、文字列の最初、中間、または最後にあります。

つまり、使用strposしないでください。ここでは役に立ちません。正規表現エンジンを使用していた場合、針を含まない干し草preg_replaceの山よりも計算が複雑になる可能性があります。strpos

于 2012-07-17T11:07:33.520 に答える
0

最適化(特にマイクロ最適化)を探している場合は、自分でベンチマークする方が良いと思います。どの実装にも (通常) 1 つ以上のバリエーションがあるため、使用したバリエーションをベンチマークすることをお勧めします。これによると、ここでベンチマーク結果を確認できます: strpos あり: http://3v4l.org/pb4hY#v533 strpos なし: http://3v4l.org/v35gT

于 2014-04-28T12:11:06.547 に答える
0

Mihai さん、ありがとうございます - これは非常に理にかなっていますが、この特定のシナリオでは、最初にデータベースからすべてのレコードを取得したとしても、つまり関連するカテゴリを持つすべての画像を取得したとしても、$string に1 つまたは 2 つの「トークン」のみ - 比較対象のカテゴリ (「トークン」) が多数ある場合、strpos() を使用すると実際に時間を節約できることを意味します。

可能性のあるすべてのレコードを以前に生成された配列に既に格納しているため、各反復でgetByCategoryを呼び出さないと想像してください- Plugin::get() メソッドと str_replace() 内で出力バッファリングを行う必要があります - つまり、 20 のカテゴリがあるとします。これは、必ずしも $string 内に「トークン」が含まれていなくても 20 回発生します。

したがって、ループしているカテゴリの数と比較して $string に多数の「トークン」が見つかった場合、あなたの提案は機能しますが、少数の「トークン」の場合、 strpos() はstrpos() が true を返したときに、次の 2 つではなく、各カテゴリに対して実行されるのは 1 つだけであるため、依然として有益です。この場合、毎回 ob と str_replace を一緒に比較して strpos() の形式で支払うのは小さな代償です。ループで-そう思いませんか?

私はあなたの説明にとても感謝しています。

于 2012-07-17T11:45:44.827 に答える