[PHP-users 20918]Re: csvファイルの読み込み

komura komura @ ma9.seikyou.ne.jp
2004年 3月 23日 (火) 15:50:48 JST


komura です。

遅くなりましたが、興味がありましたので、CLI 版の PHP で fgets() について
調べてみました。

引用が前後しています。

On Fri, 19 Mar 2004 19:58:45 +0900
Seiji Masugata <s.masugata @ digicom.dnp.co.jp> wrote:

> $Str = fgets( $PTR, 1000 )
> $Str = fgets( $PTR, 100000 )
> 
> とかも、結構(確認した時は5秒くらい)差が出ますね。

試してみると、かなりの差が出ることが確認できました。
結論としては、PHP 4.3.0 以降で fgets() を使用する場合は、第2引数は
省略する方が速いようです。

PHP 4.2.2 の CLI 版で試すと違う結果が出ましたので、PHP 4.3.x 以外では
参考にならないかもしれません。


以下のように、100万行の数字だけのファイルを作成して、PHP 4.3.5RC4 の
gets() で読み込みに掛かる時間を調べてみました。

$ php -r 'for ( $i = 0; $i < 1000000; ++$i ) { echo $i . "\n"; }' > test.txt

$ php -v
PHP 4.3.5RC4 (cli) (built: Mar 20 2004 21:51:13)
Copyright (c) 1997-2004 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies

$ time php -r '$fp = fopen( "test.txt", "r" ); while ( fgets( $fp ) ) { ; } fclose( $fp );'

real    0m2.676s
user    0m2.633s
sys     0m0.041s

$ time php -r '$fp = fopen( "test.txt", "r" ); while ( fgets( $fp, 10 ) ) { ; } fclose( $fp );'

real    0m3.386s
user    0m3.346s
sys     0m0.037s

$ time php -r '$fp = fopen( "test.txt", "r" ); while ( fgets( $fp, 100 ) ) { ; } fclose( $fp );'

real    0m5.022s
user    0m4.975s
sys     0m0.043s

$ time php -r '$fp = fopen( "test.txt", "r" ); while ( fgets( $fp, 1000 ) ) { ; } fclose( $fp );'

real    0m6.343s
user    0m6.300s
sys     0m0.040s


perl で実行した結果は以下のようになりました。

$ perl -v
This is perl, v5.8.2 built for i686-linux

$ time perl -e 'open( IN, "test.txt" ); while ( <IN> ) { ; } close( IN );'

real    0m1.592s
user    0m1.563s
sys     0m0.027s


> この場合、ダイレクトIO関数を利用した方がいいんですかね?
> http://www.php.net/dio

ダイレクト IO 関数 には、fgets() と同等の関数が無いため、比較できませんでした。
興味がありましたので、fread() との比較を行ってみましたが、通常のファイルの
読み込みでは、特に差は出ませんでした。

PHP マニュアルにあるように、デバイスの直接制御以外の用途には使わない方が
良いのかもしれません。


> 他に良い方法があれば、教えて下さい(DBは考えない方向で)。

PHP 4.3.x であれば、fgets() の第2引数を省略することで、Perl との差が少し
縮まるようです。

または、メモリに余裕があれば、以下のようにファイル全体を読み込み、正規表現を
使用して行を取得するという方法があると思います。

$ php -r '$s = file_get_contents( "test.txt" ); if ( preg_match( "/^999999,.*$/m", $s, $m ) ) { echo $m[0]; }'

-- 
komura <komura @ ma9.seikyou.ne.jp>


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