PHP の curl_multi_exec はなぜPHPなのにパラレルで処理できるのか

発端

某所で「最近のPHPcurlライブラリはパラレル取得できる」ときいて「エッなんで、PHPって基本シングルスレッドだしイベントループみたいな機構もないと認識してるんだけど」って思って調べた。

追記:と思ったが、この記事を書いた後さらに調べたら、そもそもPHP には stream_select など IO 多重化をサポートする関数群があった。不勉強であった。

なにはともあれドキュメントにあたろう

PHPは公式のドキュメントが充実していてすばらしい。これは素直に認めるべきPHPの美点だと思う。

Client URL Library

うーんなんか見た感じCで並列性を吸収してるのかな?という感じの低レベルAPIへのグルー感。じゃあ実際にソースを読んでみる

ソースを読む

https://github.com/php/php-src/blob/85d05b5654cbbbf6f741d7f9be13136746ff8c35/ext/curl/multi.c#L198

実際に並列でリクエスト投げる curl_multi_exec 関数(こいつ自体はブロッキングしない。そのあとcurl_multi_select などのブロッキングする関数でレスポンスを待つ)の定義を見に行くと、中で「curl_multi_perform」を呼んでいる。このcurl_multi_performはどうやら libcurl で定義されているっぽい。想像通り並列の部分はCレベルで吸収して解決しているようだ。その他の関数も想像通りどうやらlibcurlへ処理を委譲しているだけ。

つまり、PHPcurlライブラリがパラレルで取得できるというよりは、そもそもlibcurlにそういう機構が組み込まれていて、PHPはそれへのグルーを提供しているという話みたい。

所感

単純になるほどという感じがする。PerlRuby の文化だと、その言語自体が言語を拡張するみたいな文化があるように思う(Perl だと Moose とか Ruby だと ActiveSupport とか)けど、PHP の場合はそこは結構棲み分けがあって、「PHP でできること」の中に「PHP そのものを拡張する」ってのは入れない文化であると感じる。それによって「PHPカジュアルユーザー」はPHPの世界だけで行きて行くし、「PHPヘヴィユーザー」はCレベルでPHPの拡張モジュールとか書くとか、PHP自体を拡張しちゃう(Hackとか)という感じだよな。それはそれでひとつの考え方だよな、と感じた。