| « IEの仕様です | DokuWiki » |
_php_stream_passthru
php-usersのMLに投稿した内容の補足です。コードはPHP 4.4の開発ブランチのソースです。
main/stream.cに_php_stream_passthru関数が定義されています。reafile関数(ファイルの中身を全て出力)、fpassthru関数(ファイルリソースの中身を全て出力)に利用されています。
PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
{
size_t bcount = 0;
int ready = 0;
char buf[8192];
#ifdef HAVE_MMAP
int fd;
#endif
#ifdef HAVE_MMAP
if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET)
&& stream->filterhead == NULL
&& php_stream_tell(stream) == 0
&& SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0))
{
struct stat sbuf;
off_t off;
void *p;
size_t len;
fstat(fd, &sbuf);
if (sbuf.st_size > sizeof(buf)) {
off = php_stream_tell(stream);
len = sbuf.st_size - off;
p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off);
if (p != (void *) MAP_FAILED) {
BG(mmap_file) = p;
BG(mmap_len) = len;
PHPWRITE(p, len);
BG(mmap_file) = NULL;
munmap(p, len);
bcount += len;
ready = 1;
}
}
}
#endif
if(!ready) {
int b;
while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
PHPWRITE(buf, b);
bcount += b;
}
}
return bcount;
}
注目すべきは以下です。
if (p != (void *) MAP_FAILED) {
BG(mmap_file) = p;
BG(mmap_len) = len;
PHPWRITE(p, len);
BG(mmap_file) = NULL;
munmap(p, len);
bcount += len;
ready = 1;
}
PHPWRITEマクロは最終的に出力バッファに書き出します。PHPからの出力は最終的にWebサーバにバッファされる場合があります。つまり、一度に大量のデータを出力するとメモリを大量に必要とする可能性があります。
Momoery Mapped I/Oの利点がバッファ無しでデータを読める事は分りますが、大きなファイルを送信するには不適切な事は明らかです。データを適切なチャンクサイズに区切ってPHPWRITEに書き込むよう変更しなければならないですね...
3 コメント
今、PHP 4.4ブランチのbuildconfでconfigureスクリプト作り直して見ましたが、MMAPサポートのオプションは無いようですね...
MMAPはデフォルトでは無い方がよいと思います。configureで--with-mmapにした場合にのみMMAPを利用するべきと思います。メモリにマップするため(そのための機能なので当たり前ですが)、32bit OSではかなり致命的で、大きなファイルは扱えません。
# 追記:mmapに失敗するとready変数が未セットなので
# フォールバックしてますね。
PHPのコードは突っ込みどころが多いのでC言語を知っているあなた!是非、PHPのソースを読んで突っ込んでください。
私ではなくinternals@lists.php.netへ!
# 念のため(苦笑
# internalsは敷居が高い場合は是非、http://bugs.php.net/ へ!
MMAPはデフォルトでは無い方がよいと思います。configureで--with-mmapにした場合にのみMMAPを利用するべきと思います。メモリにマップするため(そのための機能なので当たり前ですが)、32bit OSではかなり致命的で、大きなファイルは扱えません。
# 追記:mmapに失敗するとready変数が未セットなので
# フォールバックしてますね。
PHPのコードは突っ込みどころが多いのでC言語を知っているあなた!是非、PHPのソースを読んで突っ込んでください。
私ではなくinternals@lists.php.netへ!
# 念のため(苦笑
# internalsは敷居が高い場合は是非、http://bugs.php.net/ へ!
2005/06/24 @ 00:33
ありがとうございます。ご指摘の通りです。笑いえますね(笑
# 私は驚異的なタイポする天才(!?)なのです(苦笑
# こういう指摘は本当に助かります。
# 私は驚異的なタイポする天才(!?)なのです(苦笑
# こういう指摘は本当に助かります。
2005/06/24 @ 11:07