[PHP-users 31433] Re: これは仕様?(sleep関数と非同期クエリ関数の関係)

Yoshihiro Hanahara hanahara @ meiko.co.jp
2007年 2月 9日 (金) 20:14:46 JST


花原@明宏です。


今、私が書いた[PHP-users 31397] を読み返すと日本語がかなり変ですね。また、
神谷さんのコードを斜め読みしただけで、本質的な所を誤解していたようです。
申し訳ありません。


On Fri, 09 Feb 2007 14:10:10 +0900
kamiya 谷 <djr_kamiya @ hotmail.com> wrote:

> ご指摘の点については、サンプルソースの問題なのですが、実コード
> 上は最初からsleepを行ったり・・・ということは当然のごとく試し
> ていたので、その点について触れていませんでした。
> 
> 現状確認できている状況で説明させていただくと
> usleep( 1000 );を挟んだ場合は、クエリをpsql上で実行したときと、
> ほぼ同じレスポンスで帰ってくる。(数秒)
> usleep(2000000);を挟んだ場合は、数十分かかる。
> という結果を得ています。

もうちょっと真剣に(でもやはり斜め読み ^_^;)、PHPのpgsqlや、PostgreSQLの
libpqのソースコードを見ました。

pg_send_query()、pg_connection_busy()、pg_get_result()の非同期クエリ系の
場合、マルチスレッドで並行実行しているわけではありません。単に関数呼び出
しがブロックしてしまわないようになっているだけで、本質的にはシングルスレッ
ドで、内部的にポーリングしてます(シングルスレッドだから仕方がない)。

pg_send_query()でサーバー側に送ったクエリは、サーバー側で並行実行されま
すが、サーバー側の状態を問い合わせたり、クエリの結果を取り込んだりする処
理は、クライアント側で実行されます。この部分は今のlibpqではシングルスレッ
ドなモデルで実行されますので、usleep()で止まっている間は、クライアント側
の処理も止まってしまいます。
実際のサーバー側とのやり取りは、pg_*()関数を呼びだしている内部でしか行わ
れていないので...。


> usleep( 1000 );を挟んだ場合は、クエリをpsql上で実行したときと、
> ほぼ同じレスポンスで帰ってくる。(数秒)
> usleep(2000000);を挟んだ場合は、数十分かかる。

usleep(1000)だと、頻繁にpg_*()関数に実行の機会を与えますが、
usleep(2000000)だと、2秒に一回しかその機会を与えないからではないでしょう
か?

# usleep(1000); は、usleep(10000); の10msぐらいでも対して変わらない
# 気がするけどどうですか? OSのスケジューラーのタイムクオンタムが
# 10msぐらいなので(根拠なし)。


あと、

    http://jp.php.net/manual/ja/function.usleep.php

の User Contributed Notes のところに、socket_select() を使った、usleep_win()
というのがありますが、たぶん、変わらないとは思うんだけど、やってみる価値
はあるかも。

---
Yoshihiro Hanahara <hanahara @ meiko . co . jp>





PHP-users メーリングリストの案内