PHPにsqlite_free_resultが無い訳
2008年1月7日
PHP マニュアルより
PHP4のZendエンジンに導入されたリファレンスカウンティングシステムのおかげで、あるリソースがもう参照されなくなった場合に(Javaと全く 同様に)、そのリソースは自動的に削除されます。この場合、このリソー スが作成した全てのリソースはガーベッジコレクタにより開放されます。 このため、free_result関数を用いて手動でメモリを開放する必要が生じるのはまれです。
注意: 持続的データベース接続は特別で、ガーベッジコレクタにより破棄されません。
ガベージコレクタが自動的にやってくれるということらしい。持続的接続の場合にどうするかということだが、そういう場合はfree_resultが必要な処理は行うなということかもしれない。どちらにせよ、私は持続的接続は使わないだろうから、この機能があっても無くてもいいんだけれど。
PHP4のZendエンジンに導入されたリファレンスカウンティングシステムのおかげで、あるリソースがもう参照されなくなった場合に(Javaと全く 同様に)、そのリソースは自動的に削除されます。この場合、このリソー スが作成した全てのリソースはガーベッジコレクタにより開放されます。 このため、free_result関数を用いて手動でメモリを開放する必要が生じるのはまれです。
注意: 持続的データベース接続は特別で、ガーベッジコレクタにより破棄されません。
ガベージコレクタが自動的にやってくれるということらしい。
コメント
hsur (2008年1月13日 07:50:15)
持続的データベース接続がGCにより破棄されないというのは、DB接続自体が破棄されないというだけで、接続を通じて取得したresultはGCで破棄されると考えてよいのではないでしょうか。
# 日本語は「注意:」になっていますが、原文は「Note:」でした。
# 持続的データベース接続をGCで破棄してしまうとその要をなさないので、それがGCの例外であるということを述べているだけだと思います。
# 日本語は「注意:」になっていますが、原文は「Note:」でした。
# 持続的データベース接続をGCで破棄してしまうとその要をなさないので、それがGCの例外であるということを述べているだけだと思います。
Kat (2008年1月13日 12:45:20)
Warning: comments::cb1_tag_body(): Argument #1 ($m) must be passed by reference, value given in /home/u109394186/domains/rad51.net/public_html/jeans/jeans/libs/comments.php on line 51
なるほど、そういうことなのかもしれません。原文を見てみました。
Note: Persistent database links are special, they are not destroyed by the garbage collector. See also the section about persistent connections.
これを読むだけでは『they』が『persistent database links』を指すのか、『resources』を指すのか分かりませんね。『links』を指すのなら、『are special and not destroyed』となりそうなのですが、自信ありません。ちょっと、実験してみます。
Kat (2008年1月13日 14:42:13)
調べてみました。まず、プロセス越しにリソースを受け渡す方法は、sql_popenによるデータベースの再オープンしかないようです。つまり、sql_query関数の戻り値としてのリソースをプロセス越しに受け渡すことは出来ないので、必然的に、このリソースはGCにより破棄されると思われます(hsurさんのおっしゃるとおり)。
実験してみて面白かったのは、持続的接続の際、データベースへの接続は確かにスピードアップされるのですが、クエリー発行の際に非持続的接続のときよりも余計に時間がかかることです。これはSQLiteの例なので、他のデータベースエンジンではどうだか分かりませんが。
実験してみて面白かったのは、持続的接続の際、データベースへの接続は確かにスピードアップされるのですが、クエリー発行の際に非持続的接続のときよりも余計に時間がかかることです。これはSQLiteの例なので、他のデータベースエンジンではどうだか分かりませんが。
hsur (2008年1月14日 04:53:21)
ベンチマークの結果が面白いですね。
コネクションプーリングはコネクションを新しく作るコスト>>コネクションを使いまわすためのオーバーヘッドといいう場合に効果が大きくなるはずなんですが、sqliteはその比が逆転しているのかもしれませんね。
コネクションプーリングはコネクションを新しく作るコスト>>コネクションを使いまわすためのオーバーヘッドといいう場合に効果が大きくなるはずなんですが、sqliteはその比が逆転しているのかもしれませんね。
Kat (2008年1月14日 10:51:45)
もう少し調べてみました。結果としては、やはりsql_popenの方が、すべてのケースにおいて早いようです。
sqlite_popenを使用:
37 micro seconds for opening db
140 micro seconds for query
62 micro seconds for query
db:Resource id #2, res:Resource id #4
sqlite_openを使用:
751 micro seconds for opening db
65 micro seconds for query
61 micro seconds for query
db:Resource id #2, res:Resource id #4
昨日の実験では一回のプロセスでクエリーを一度しか発行していなかったので、『クエリー発行の際に非持続的接続のときよりも余計に時間がかかる』と結論付けていました。が、2回目以降のクエリー発行は、sql_openと同じスピードで行われることが分かりました。結果として、sql_popenを利用したほうが、DB接続で700μ秒早く、最初のクエリー発行で100μ秒遅い、つまりトータルで600μ秒早いと言う結論になりました。
popenの場合、リソースが特殊なメモリ領域に保存されるでしょうから、そのメモリ領域にアクセスする権限を所得するのに、100μ秒かかるのでしょう。一度アクセスすれば通常メモリ領域にもキャッシュされるので、二度目以降は余計な権限取得は要らないのだと思います。
sqlite_popenを使用:
37 micro seconds for opening db
140 micro seconds for query
62 micro seconds for query
db:Resource id #2, res:Resource id #4
sqlite_openを使用:
751 micro seconds for opening db
65 micro seconds for query
61 micro seconds for query
db:Resource id #2, res:Resource id #4
昨日の実験では一回のプロセスでクエリーを一度しか発行していなかったので、『クエリー発行の際に非持続的接続のときよりも余計に時間がかかる』と結論付けていました。が、2回目以降のクエリー発行は、sql_openと同じスピードで行われることが分かりました。結果として、sql_popenを利用したほうが、DB接続で700μ秒早く、最初のクエリー発行で100μ秒遅い、つまりトータルで600μ秒早いと言う結論になりました。
popenの場合、リソースが特殊なメモリ領域に保存されるでしょうから、そのメモリ領域にアクセスする権限を所得するのに、100μ秒かかるのでしょう。一度アクセスすれば通常メモリ領域にもキャッシュされるので、二度目以降は余計な権限取得は要らないのだと思います。
hsur (2008年1月16日 16:33:48)
思ったよりもsqlite_openはコストがかかっているんですね。参考になりました。
Kat (2008年1月18日 18:03:41)
一つ補足です。行った実験は、WinXP home editionでですから、お世辞にも良い環境とは言えないです。ファイルを一つ開くのにおおよそ500μ秒を要しているようですから、これがsqlite_openにコストがかかる主な原因です。このあたりの挙動は、OSが違うとずいぶん変わると思います。