BugTrack/2102
の編集
Top
/
BugTrack
/
2102
[
トップ
] [
編集
|
差分
|
履歴
|
添付
|
リロード
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
*添付ファイルダウンロード等の効率化 [#o0ea77b9] -ページ: [[BugTrack]] -投稿者: [[三浦克介]] -優先順位: 低 -状態: 完了 -カテゴリー: 本体バグ -投稿日: 2005-08-29 (月) 21:30:53 -バージョン: 1.4.5 -リリース予定バージョン: 1.5.2 ** 関連 [#i22d64e7] - [[BugTrack/632]] PHP5で動作しない **メッセージ [#h2718e23] (readfileの利用は継続。出力バッファリングを明示的にOFFにする対応を行いました (2017-08-23 by umorigu)) ---- PHP 5.0.4 には、readfile() や fpassthru() が 2000000 バイトで停止してしまうというバグがあるらしいです。 http://bugs.php.net/bug.php?id=32553 プラグイン attach, dump, ref で readfile が使われており、例えば、2000000バイトを越える添付ファイルをダウンロードすると、2000000バイトで切れてしまいます。 PHP 5.0.4 以外では大丈夫だと思いますが、readfile はファイル内容を一度メモり上に読み込みますので、あまり、サーバーに優しくありません。また、readfile よりも、echo fread() を繰り返した方が高速らしいです。 http://jp.php.net/readfile という訳で、readfile を使っている部分を、echo fread() で置き換えませんか? 例えば、attach.inc.php は以下のようになります。 Index: attach.inc.php =================================================================== RCS file: /cvsroot/pukiwiki/pukiwiki/plugin/attach.inc.php,v retrieving revision 1.79 diff -c -r1.79 attach.inc.php *** attach.inc.php 8 Aug 2005 14:54:15 -0000 1.79 --- attach.inc.php 29 Aug 2005 12:32:28 -0000 *************** *** 659,665 **** header('Content-Length: ' . $this->size); header('Content-Type: ' . $this->type); ! @readfile($this->filename); exit; } } --- 659,672 ---- header('Content-Length: ' . $this->size); header('Content-Type: ' . $this->type); ! $handle = fopen($this->filename, 'rb'); ! while (!feof($handle)) ! { ! echo fread($handle, 4096); ! flush(); ! } ! fclose($handle); ! exit; } } fopen できなかった時はどうすべきですかね? @readfile となっているのに合わせて、なにも表示せずに exit? **参考 [#kf367aea] -[[BugTrack2/70]] ---- -(性能を検討した上で)[[BugTrack/779]] -- &new{2005-08-30 (火) 00:15:57}; -attachプラグインはreadfileの前にファイルがあるかどうか確認していますので、なにも表示せずにexitでも良さそうな気がします。 -- [[teanan]] &new{2005-08-30 (火) 03:09:46}; -あと、readfileを使ってるところは dump と ref プラグインですが、dumpプラグインはバグの影響がありそうですね (^^; -- [[teanan]] &new{2005-08-30 (火) 03:16:21}; -形にする場合は、echo_readfile() といった別個の関数にするのが良さそうですね ;) 中身はfread()のマニュアルにある通り「 伝統的な while(!feof()) を使うアプローチよりも パフォーマンス的にベター」という方法が・・・あ、メモリ使いそうだ (^^; -- [[henoheno]] &new{2005-08-30 (火) 23:10:03}; -- 「fread() に与える最も効率のいい値」が入った定数(環境ごとに違う値を期待する)て無いのかしらん。マニュアルでは8K決め打ちのようですね。環境決め打ちで良いなら、何度か試すと大体わかるかな? -- [[henoheno]] &new{2005-08-30 (火) 23:10:55}; -その他の視点: PHP 5.0.4 はPHP5系の最新バージョンであり、そのユーザーはより新しいバージョンを使いたがると思われるため、個別のバージョンのフォローは個別に対応(回避)していただくという対応もあるかと思われます。 -- [[henoheno]] &new{2005-08-30 (火) 23:19:39}; -デメリットは無いようなので変更して良いと思いますが。freadのサイズはob_get_lengthから拾うのが良いような感じですが既にheader等を貯めてる%%気がする%%(数行上でheader出してますから貯めてますね)((詳しく追ってません))のでflushはループの前で1回コールが良いのかも -- [[Cue]] &new{2005-09-03 (土) 00:37:56}; - こちらの件は 5.0.5 で直ったと考えてよろしいのでしょうか? であれば 5.0.4 特有の問題として考えたく思います。 -- [[henoheno]] &new{2005-10-31 (月) 23:29:59}; -- 5.0.3 と 5.0.4 が該当するバージョンのようです。5.0.5 で FIX です。 -- [[kawai]] &new{2005-11-05 (土) 21:09:22}; -- main/php_streams.h で PHP_STREAM_COPY_ALL が定義されていて、それを利用する関数を追いかけると見つかりますね。 -- [[kawai]] &new{2005-11-05 (土) 21:18:23}; - PHPのバグで http://wiki.ohgaki.net/index.php?cmd=read&page=PHP%2Fpatch%2FMMAP%A4%F2%CC%B5%B8%FA%B2%BD で直ります。pukiwikiのソースでも対応しておいた方が良いとは思いますが情報として。 -- [[yohgaki]] &new{2005-11-10 (木) 11:34:00}; - メモリの使用量が全然違うので、是非適用願います。php.iniでメモリに400MByte割り当てても、120MByte程度のファイルをダウンロードしようとしたらメモリが足りなくなって死にました。(WinXPのIE6でDLすると、サイズ0byteのファイルができました。)1000MByte割り当てたらOKでした。&br;上の修正をそのまま適用したら、400MByteのままでも問題ありませんでした。 -- [[ぃぉぃぉ]] &new{2007-07-31 (火) 01:26:46}; -- 上で過去の自分も(想像ベースであいまいに)言っていたようですが、平均のメモリ消費量が下がるというのであれば意味がありますね -- [[henoheno]] &new{2007-08-05 (日) 21:24:35}; -- 推測ですが、この修正によって最大使用メモリが一定値になります。修正前だとDLするファイルサイズに依存して消費メモリが際限なく増えます。phpの関数readfileの内部仕様が変わらない限りは、ですが。 -- [[ぃぉぃぉ]] &new{2007-08-05 (日) 23:01:28}; - readfileのマニュアル([[php.net:manual/ja/function.readfile.php]]) に「注意: readfile() 自体にはメモリに関する問題はなく、 巨大なファイルを送ってもかまいません。」とあるように、バッファリングOFFになっていればreadfileで大量メモリを消費してしまうことはないようです。 jyn.jp/php-readfile-memory/ こちらのブログでも検証されていました。(カスタマイズ・設定で)バッファリングがONになっていることがあるようなのでその対処をすれば解決ですね。PHP5.0.4はもう古いのでバージョン固有バグへの対応はしません -- [[umorigu]] &new{2017-08-23 (水) 05:30:24}; -- 念のためPHPソースを見てみると [[file.c>github.com:php/php-src/blob/php-7.1.0/ext/standard/file.c#L1348]] readfile() から php_stream_passthru() を呼び出していて、[[stream.c>github.com:php/php-src/blob/php-7.1.0/main/streams/streams.c#L1384]] この中で8KBずつPHPWRITE (php_output_write())が呼ばれていました。 [[output.c>github.com:php/php-src/blob/php-7.1.0/main/output.c#L254]] つまり、マニュアルの記述通り、「readfile はファイル内容を一度メモり上に読み込」むことはなく、大容量ファイルも扱えます -- [[umorigu]] &new{2017-08-23 (水) 05:44:17}; - タイトル変更しました。「PHP 5.0.4 バグ対策&添付ファイルダウンロード等の効率化」→「添付ファイルダウンロード等の効率化」 -- [[umorigu]] &new{2017-08-23 (水) 05:35:19}; - readfileの直前に出力バッファリングがされていればOFFにするようにしました。 commit:cd237d77fb -- [[umorigu]] &new{2017-08-23 (水) 06:10:34}; #comment
タイムスタンプを変更しない
*添付ファイルダウンロード等の効率化 [#o0ea77b9] -ページ: [[BugTrack]] -投稿者: [[三浦克介]] -優先順位: 低 -状態: 完了 -カテゴリー: 本体バグ -投稿日: 2005-08-29 (月) 21:30:53 -バージョン: 1.4.5 -リリース予定バージョン: 1.5.2 ** 関連 [#i22d64e7] - [[BugTrack/632]] PHP5で動作しない **メッセージ [#h2718e23] (readfileの利用は継続。出力バッファリングを明示的にOFFにする対応を行いました (2017-08-23 by umorigu)) ---- PHP 5.0.4 には、readfile() や fpassthru() が 2000000 バイトで停止してしまうというバグがあるらしいです。 http://bugs.php.net/bug.php?id=32553 プラグイン attach, dump, ref で readfile が使われており、例えば、2000000バイトを越える添付ファイルをダウンロードすると、2000000バイトで切れてしまいます。 PHP 5.0.4 以外では大丈夫だと思いますが、readfile はファイル内容を一度メモり上に読み込みますので、あまり、サーバーに優しくありません。また、readfile よりも、echo fread() を繰り返した方が高速らしいです。 http://jp.php.net/readfile という訳で、readfile を使っている部分を、echo fread() で置き換えませんか? 例えば、attach.inc.php は以下のようになります。 Index: attach.inc.php =================================================================== RCS file: /cvsroot/pukiwiki/pukiwiki/plugin/attach.inc.php,v retrieving revision 1.79 diff -c -r1.79 attach.inc.php *** attach.inc.php 8 Aug 2005 14:54:15 -0000 1.79 --- attach.inc.php 29 Aug 2005 12:32:28 -0000 *************** *** 659,665 **** header('Content-Length: ' . $this->size); header('Content-Type: ' . $this->type); ! @readfile($this->filename); exit; } } --- 659,672 ---- header('Content-Length: ' . $this->size); header('Content-Type: ' . $this->type); ! $handle = fopen($this->filename, 'rb'); ! while (!feof($handle)) ! { ! echo fread($handle, 4096); ! flush(); ! } ! fclose($handle); ! exit; } } fopen できなかった時はどうすべきですかね? @readfile となっているのに合わせて、なにも表示せずに exit? **参考 [#kf367aea] -[[BugTrack2/70]] ---- -(性能を検討した上で)[[BugTrack/779]] -- &new{2005-08-30 (火) 00:15:57}; -attachプラグインはreadfileの前にファイルがあるかどうか確認していますので、なにも表示せずにexitでも良さそうな気がします。 -- [[teanan]] &new{2005-08-30 (火) 03:09:46}; -あと、readfileを使ってるところは dump と ref プラグインですが、dumpプラグインはバグの影響がありそうですね (^^; -- [[teanan]] &new{2005-08-30 (火) 03:16:21}; -形にする場合は、echo_readfile() といった別個の関数にするのが良さそうですね ;) 中身はfread()のマニュアルにある通り「 伝統的な while(!feof()) を使うアプローチよりも パフォーマンス的にベター」という方法が・・・あ、メモリ使いそうだ (^^; -- [[henoheno]] &new{2005-08-30 (火) 23:10:03}; -- 「fread() に与える最も効率のいい値」が入った定数(環境ごとに違う値を期待する)て無いのかしらん。マニュアルでは8K決め打ちのようですね。環境決め打ちで良いなら、何度か試すと大体わかるかな? -- [[henoheno]] &new{2005-08-30 (火) 23:10:55}; -その他の視点: PHP 5.0.4 はPHP5系の最新バージョンであり、そのユーザーはより新しいバージョンを使いたがると思われるため、個別のバージョンのフォローは個別に対応(回避)していただくという対応もあるかと思われます。 -- [[henoheno]] &new{2005-08-30 (火) 23:19:39}; -デメリットは無いようなので変更して良いと思いますが。freadのサイズはob_get_lengthから拾うのが良いような感じですが既にheader等を貯めてる%%気がする%%(数行上でheader出してますから貯めてますね)((詳しく追ってません))のでflushはループの前で1回コールが良いのかも -- [[Cue]] &new{2005-09-03 (土) 00:37:56}; - こちらの件は 5.0.5 で直ったと考えてよろしいのでしょうか? であれば 5.0.4 特有の問題として考えたく思います。 -- [[henoheno]] &new{2005-10-31 (月) 23:29:59}; -- 5.0.3 と 5.0.4 が該当するバージョンのようです。5.0.5 で FIX です。 -- [[kawai]] &new{2005-11-05 (土) 21:09:22}; -- main/php_streams.h で PHP_STREAM_COPY_ALL が定義されていて、それを利用する関数を追いかけると見つかりますね。 -- [[kawai]] &new{2005-11-05 (土) 21:18:23}; - PHPのバグで http://wiki.ohgaki.net/index.php?cmd=read&page=PHP%2Fpatch%2FMMAP%A4%F2%CC%B5%B8%FA%B2%BD で直ります。pukiwikiのソースでも対応しておいた方が良いとは思いますが情報として。 -- [[yohgaki]] &new{2005-11-10 (木) 11:34:00}; - メモリの使用量が全然違うので、是非適用願います。php.iniでメモリに400MByte割り当てても、120MByte程度のファイルをダウンロードしようとしたらメモリが足りなくなって死にました。(WinXPのIE6でDLすると、サイズ0byteのファイルができました。)1000MByte割り当てたらOKでした。&br;上の修正をそのまま適用したら、400MByteのままでも問題ありませんでした。 -- [[ぃぉぃぉ]] &new{2007-07-31 (火) 01:26:46}; -- 上で過去の自分も(想像ベースであいまいに)言っていたようですが、平均のメモリ消費量が下がるというのであれば意味がありますね -- [[henoheno]] &new{2007-08-05 (日) 21:24:35}; -- 推測ですが、この修正によって最大使用メモリが一定値になります。修正前だとDLするファイルサイズに依存して消費メモリが際限なく増えます。phpの関数readfileの内部仕様が変わらない限りは、ですが。 -- [[ぃぉぃぉ]] &new{2007-08-05 (日) 23:01:28}; - readfileのマニュアル([[php.net:manual/ja/function.readfile.php]]) に「注意: readfile() 自体にはメモリに関する問題はなく、 巨大なファイルを送ってもかまいません。」とあるように、バッファリングOFFになっていればreadfileで大量メモリを消費してしまうことはないようです。 jyn.jp/php-readfile-memory/ こちらのブログでも検証されていました。(カスタマイズ・設定で)バッファリングがONになっていることがあるようなのでその対処をすれば解決ですね。PHP5.0.4はもう古いのでバージョン固有バグへの対応はしません -- [[umorigu]] &new{2017-08-23 (水) 05:30:24}; -- 念のためPHPソースを見てみると [[file.c>github.com:php/php-src/blob/php-7.1.0/ext/standard/file.c#L1348]] readfile() から php_stream_passthru() を呼び出していて、[[stream.c>github.com:php/php-src/blob/php-7.1.0/main/streams/streams.c#L1384]] この中で8KBずつPHPWRITE (php_output_write())が呼ばれていました。 [[output.c>github.com:php/php-src/blob/php-7.1.0/main/output.c#L254]] つまり、マニュアルの記述通り、「readfile はファイル内容を一度メモり上に読み込」むことはなく、大容量ファイルも扱えます -- [[umorigu]] &new{2017-08-23 (水) 05:44:17}; - タイトル変更しました。「PHP 5.0.4 バグ対策&添付ファイルダウンロード等の効率化」→「添付ファイルダウンロード等の効率化」 -- [[umorigu]] &new{2017-08-23 (水) 05:35:19}; - readfileの直前に出力バッファリングがされていればOFFにするようにしました。 commit:cd237d77fb -- [[umorigu]] &new{2017-08-23 (水) 06:10:34}; #comment
テキスト整形のルールを表示する