シンプルなPHPマルチスレッド実装

PHPのマルチスレッド化は「すぐに使用可能」ではないため、拡張機能pthreadsAzaThread (CThread)、さらにはPHP開発者自身の開発など、その実装のために非常に多くのオプションが考案されました。



私にとっての主な欠点は、これらのソリューションにとって「余計なもの」が多すぎることでした。スレッドと親プロセス間で情報を交換したり、リソースを節約したりする必要は必ずしもありません。 問題を迅速かつ費用対効果の高い方法で解決する能力が常にあるべきです。



この投稿で大きな秘密が開かれないように事前に予約したい-言語の初心者にとってより可能性が高いので、私は自分で問題に遭遇したためにそれを公開することを決めました。



したがって、タスクは、スクリプトに来た大量のデータを処理することです。 私の仕事は、テキスト情報のJSON配列を処理し、スクリプトがそれを収集してPostgreSQLの同様に大きなコミットを収集する必要があることを消化することでした。



まず、親ファイルのデータを収集します。



index.php



// bigdata.json -    .      - ,     .. $big_json = file_get_contents('bigdata.json'); $items = json_decode($big_json, true); //   php    ,    , ,  unset($big_json); // ...
      
      





配列サイズは約400 mbで変動し(後で50 mbに縮小されました)、すべての情報はテキスト形式でした。 すべてが消化される速度を推定することは難しくありません。また、スクリプトは15分ごとにcronで実行され、処理能力はまあまあなので、パフォーマンスは非常に低下しました。



データを受け取った後、そのボリュームを推定し、必要に応じて各CPUコアに必要なスレッド数を計算するか、4つのスレッドがあると判断して各スレッドの行数を計算できます。



index.php



  // ... $threads = 4; $strs_per_thread = ceil(count($items) / $threads); //      -   echo "Items: ".count($items)."\n"; echo "Items per thread: ".$strs_per_thread."\n"; echo "Threads: ".$threads."\n"; // ...
      
      





すぐに言及する価値があります。このような「直接的な」計算では、各ストリームの要素数による正確な結果は得られません。 計算を簡素化する可能性が高くなります。



そして今、まさにその本質-私たちは各スレッドのタスクを作成して実行します。 この「額」を実行します-2番目のファイル-thread.phpのタスクを作成します。 これは「ストリーム」として機能し、メインスクリプトから独立して処理および開始するためのさまざまな要素を受け取ります。



index.php



  // ... for($i = 0; $i < $threads; $i++){ if($i == 0) { passthru("(php -f thread.php 0 ".$strs_per_thread." & ) >> /dev/null 2>&1"); } if($i == $threads-1) { passthru("(php -f thread.php ".($strs_per_thread * $i)." ".count($items)." & ) >> /dev/null 2>&1"); } if(($i !== 0)&&($i !== $threads-1)) { $start = $strs_per_thread * $i + 1; $end = $start -1 + $strs_per_thread; passthru("(php -f thread.php ".$start." ".$end." & ) >> /dev/null 2>&1"); } } // ...
      
      





passthru()関数はコンソールコマンドを実行するために使用されますが、スクリプトはそれぞれが完了するまで待機します。 これを行うには、プロセスを開始し、すぐに何も返さず、プロセスを開始する一連のステートメントでstartコマンドをラップします。親プロセスは、各子の実行を待機しなくなります。



 #  ,    ,   Linux- (php -f thread.php start stop & ) >> /dev/null 2>&1
      
      





残念ながら、ここで何が起こっているのかは確かではありません。おなじみのLinuxoidから一連のパラメーターが提案されました。 コメントでこの魔法を解読できれば、感謝し、投稿を補足します。



ファイルthread.php:



 $start = $argv[1]; $stop = $argv[2]; for ($i = $start; $i <= $stop; $i++) { // -          }
      
      





これで、非常に簡単な方法で、PHPにマルチスレッドエミュレーションを実装できます。



例全体をドライ出力に減らすと、次のように聞こえると思います。コマンドラインを介した親スレッドが子プロセスを起動し、処理する情報を伝えます。



「エミュレーション」と言うとき、この実装方法では、スレッド間または親スレッドと子スレッド間で情報を交換する方法がないことを意味します。 このような機能が必要ないことが事前にわかっている場合に適しています。



All Articles