問題は、なぜこのスクリプトを頻繁に実行しているのかということだと思います。同じデータに対して計算 (文字列の置換) を何度も実行していますか、それとも毎回異なるデータに対して実行していますか?
答えが前者の場合、PHP 側でパフォーマンスを改善するためにできることはこれ以上ありません。より優れたハードウェア (ファイルの読み取り/書き込みを高速化するための SSD)、マルチコア CPU を使用し、データを同時に複数のスクリプトを実行して小さな断片に分割し、データを同時に処理する、およびより高速な RAM を使用するなど、他の方法でパフォーマンスを向上させることができます。 (つまり、より高速なバス速度)。
答えが後者の場合は、memcached や reddis (キー/値キャッシュ ストア) などを使用して結果をキャッシュすることを検討してください。これにより、計算を 1 回しか実行できず、メモリからの単なる線形読み取りになります。これは非常に重要です。安価で、実質的に CPU オーバーヘッドがありません (このレベルで CPU キャッシュを利用することもできます)。
PHP での文字列操作は、基本的に単なるバイト配列であるため、すでに安価です。ファイルをメモリに読み込んで文字列に格納する際の PHP のオーバーヘッドは事実上ありません。パフォーマンスの問題が発生している場所とベンチマークの数値を示すサンプル コードがあれば、より良いアドバイスが得られるかもしれませんが、現時点では、根本的なニーズに基づいてアプローチをリファクタリングする必要があるようです。
たとえば、さまざまな状況でデータを処理する場合、CPU と I/O の両方のコストを個別に考慮する必要があります。I/O はシステム コールであるため、ブロッキングを伴います。これは、CPU がそのデータの処理または計算を続行する前に、(ディスクがメモリにデータを転送している間) ネットワーク経由でさらにデータが来るのを待つ必要があることを意味します。CPU は常にメモリよりもはるかに高速であり、メモリは常にディスクよりも高速です。
違いを示す簡単なベンチマークを次に示します。
/* First, let's create a simple test file to benchmark */
file_put_contents('in.txt', str_repeat(implode(" ",range('a','z')),10000));
/* Now let's write two different tests that replace all vowels with asterisks */
// The first test reads the entire file into memory and performs the computation all at once
function test1($filename, $newfile) {
$start = microtime(true);
$data = file_get_contents($filename);
$changes = str_replace(array('a','e','i','o','u'),array('*'),$data);
file_put_contents($newfile,$changes);
return sprintf("%.6f", microtime(true) - $start);
}
// The second test reads only 8KB chunks at a time and performs the computation on each chunk
function test2($filename, $newfile) {
$start = microtime(true);
$fp = fopen($filename,"r");
$changes = '';
while(!feof($fp)) {
$changes .= str_replace(array('a','e','i','o','u'),array('*'),fread($fp, 8192));
}
file_put_contents($newfile, $changes);
return sprintf("%.6f", microtime(true) - $start);
}
上記の 2 つのテストはまったく同じことを行いますが、少量のデータ (このテストでは約 500KB ) を使用している場合は、 Test2の方が大幅に高速であることがわかります。
実行できるベンチマークは次のとおりです...
// Conduct 100 iterations of each test and average the results
for ($i = 0; $i < 100; $i++) {
$test1[] = test1('in.txt','out.txt');
$test2[] = test2('in.txt','out.txt');
}
echo "Test1 average: ", sprintf("%.6f",array_sum($test1) / count($test1)), "\n",
"Test2 average: ", sprintf("%.6f\n",array_sum($test2) / count($test2));
私にとって、上記のベンチマークはTest1 average: 0.440795
とを与えますTest2 average: 0.052054
。これは桁違いの違いであり、500KB のデータでテストしているだけです。ここで、このファイルのサイズを約 50MB に増やすと、反復ごとのシステム I/O 呼び出しが少なくなるため (つまり、 Test1 でメモリから線形に読み取るだけなので)、 Test1の方が実際には高速であることがわかりますが、CPU コストは高くなります (つまり、反復ごとにはるかに大きな計算を実行しています)。一般に、CPU は、I/O デバイスがバス経由で送信できるよりもはるかに大量のデータを一度に処理できることが証明されています。
そのため、ほとんどの場合、万能のソリューションではありません。