ふむ。
(ノ・・)ン。。。。。。(((●コロコロッ
IBMの記事。
http://www.ibm.com/developerworks/opensource/library/os-php-multitask/
読んだ人もいるかと思う。
PHPでマルチタスク実装というのは無いなと思っていたが、
こんな方法で実現出来るのかぁ。と思った。
ただ、コードを見るかぎりでは、
実装が複雑でこれを使うにはかなり検証が必要なのが解る。
そうすると実際の利用場面は?
いろいろ考えてみたが、
これといって思いつかない。
一つ思いつくのがRSSリーダのようなクローラを実装する時。
大量にあるRSSのURLからデータを取得する際、
クローラーが一つ一つデータを取得しようとすると、
データが取れるまで待ちが発生するので、
量が多ければ多いほど時間がかかる。
Web Service APIでRESTやXMLRPC, SOAPなどを複数利用する場合も当てはまる。
ということで[大量のアクセス先からデータを取ってくる実装をマルチタスクで行う]という路線で、
もうちょっと簡単な実装を模索してみると、
面白いものがあった。
それは
curl_multi_add_handle
curl_multi_exec
[More:]
cURLには初めからマルチタスク動作する仕組みが付いている。
PHPは所詮インタフェースでしかないので、
ライブラリに渡してしまってからの動作はPHPに関係がないはず。
ならばそれを利用すればマルチ動作も可能では無かろうか?
ちょっと比較し検証してみよう。
環境は
Cli版PHP5.2.4
測定は
xdebug+Wincachegrind
ここに表示されている数値は実際の動作速度よりもトレースしている分遅いので注意。
まずはソースから。
コピペするとページを埋め尽くしてしまうので、
ファイルを置いておく。
●シングル
http://hain.jp/media/blogs/tech-j/curl_init.phps
●マルチ
http://hain.jp/media/blogs/tech-j/curl_multi_init.phps
簡単に言うと、
4つのサイトにアクセスしデータをそのまま取ってくる。
取ってくる手法が直列か並列かの違いだけ。
次に結果。
●シングル
●マルチ
Webサイトはアクセスの度に取得時間が変わるので、
一概には言えないわけだが、
全体を通しても1,000ms程度差がでている。
シングルタスクのcurl_execが一サイトに要している時間は、
93ms
587ms
604ms
1032ms
これが数珠繋ぎになるのでそりゃ時間かかるよねってところだ。
マルチの場合は一番取得に時間が長いサイトに依存している形と言える。
サイト数が多ければ多いほど顕著に差が出ると思われる。
クローラの実装には都合が良いかもしれない。
少し考察。
結果が一回だけでは信用出来ないから、
5回程試した結果をtotalだけ一覧にしてみると。
| 回数(回目) | シングル(mx) | マルチ(ms) |
| 1 | 2647 | 928 |
| 2 | 2192 | 1193 |
| 3 | 2739 | 953 |
| 4 | 2340 | 1206 |
| 5 | 2558 | 946 |
直列と並列の差はそれなりに出ているようだ。
マルチタスクの実装法だがdo-whileはもう少しイベントドリブンにしたい。
その方がエラー処理もしやすい。
が、今のところ方法が見つかっていない。
curl_multi_execのコールが1万回というのは穏やかじゃない。
このままではすべてが完了するまでサーバがフルパワーで動くことになるので、
状況によってはusleepでも入れる方が良いのかも。
stream_selectや
stream_socket_clientの用に汎用性はないものの、
こっちの方がお手軽で実用的ではないかと思う。
しばらく使って様子を見るとする。