[PHP-users 7383] Re: メモリ使用を最小限に抑えるファイル読み込み

Naomasa Numajiri php-users@php.gr.jp
Sat, 11 May 2002 00:09:36 +0900


こんばんは、

質問内容のポイントはPerl言語上でも同様だと思いますので、
「まずは同じ内容をPerlでトライして、それをPHPで書き直す」という
のはどうでしょう?

<前略>
| > fgetsで指定したバイトが大きければ大きいほど、
| > 無駄にバイト確保されてしまうということですが、

問題なのは「無駄にバイトを確保」することではなく、「"無駄に確保
されたバイト"が他のプロセスを圧迫する」ことだと思います。
(前者がYesなら、後者がYesの可能性は高くなりますが、同じこと
  ではありません。)
# メモリ容量が、利用用途に対して十分ある(=スワップが発生しない)なら、
# 別に「無駄に確保」していても僕は気にしません。

| >
| > $fp = fopen("hoge.txt", 'r');
| > while ( !feof($fp) ) {
| >   echo fgets($fp, 9182)."<この行はここで終わり>";

# ちなみに、なぜ9182?
# 8192の間違い?(まあ、あまり重要ではないですが (^^) )

| > }
| > fclose($fp);
| >
| > 上のように、1行ごとの処理をしたい場合は、
| > 行ごとのバイト数にばらつきがあるとかなり無駄にメモリを使ってしまいます。
| > そこで、ereg関数を使って\nを探し出し、そこまでで読み込みを終わらせ、
| > 次の読み込み処理へ移る…というようなことはできないでしょうか?
| 
|   一行が 9KB もあるテキストファイルというのもあまり想像できないので、
| 何をしたいのかがいまいち分からないのですが、まずは自分でいろいろ考えて
| 試しにプログラミングしてみるのが第一歩ではないでしょうか?

賛成に一票。

| 
|   あまり効率化してはいませんが、例えばこんな方法を考えてみました。
| 
| <?php
| define('FILENAME', '/etc/termcap');
| define('READ_LENGTH', 100);

なんとなくですが、僕はいつも512(=HDDのセクタサイズ)の倍数にして
います。(ていうか、PHPでのファイル操作はバッチファイルでしか使った
ことがないので、いつも8192っす(^^; それでも空きメモリは十分あるんで)

| 
| $fp = fopen(FILENAME, 'r');
| $contents = null;
| for (;;) {
|   $contents .= fread($fp, READ_LENGTH);
|   for (;;) {
|     $pos = strpos($contents, "\n");
<中略>
| 
| > 最も効率の良い、1行ごとに処理するファイルの読み込み法を探しています。
| 
|   あらゆる場合でも「最も」効率の良い方法など、実際には世の中に存在しま
| せんし、それを自ら考えることなく容易に外に求めても、決して答は見つかり
| ませんよ。

これも賛成に一票
チューニングって突き詰めていくとバランス(≒割り切り)の問題になるので、
利用用途を(プログラミングの視点から)どれだけ明確にできるかにかかって
いると思います。

参考になれば。

-- ぬ