[PHP-users 20827]csvファイルの読み込み
Seiji Masugata
s.masugata @ digicom.dnp.co.jp
2004年 3月 19日 (金) 19:58:45 JST
こんにちわ、桝形です。
10万件くらいあるcsvファイル(1レコードは可変)を上から順に検索
した時に、fgets関数が結構な負荷になるようです。
巨大なファイルを上から順にサーチするという行為自体はともかく。
しかし、Perlだと、そんなに苦ではないんですよね。
PHPの場合、ストリーム経由でデータを取得するから、その分、負荷に
なっているんでしょうか?
ext/standard/file.c:
PHPAPI PHP_FUNCTION(fgets)
main/streams.c:
PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen,
size_t *returned_len TSRMLS_DC)
static void php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC)
とか見てみたのですが、一朝一夕に分かる代物では無かった。。。
で、結局、検索方法自体を見直して、Perlと同様の検索結果を得る事は
できたんですが、改善した方法としては、fgetsの回数を減らすように
しただけ(予めINDEXを作って目的の位置までseekしてfgets、もしくは
2分検索で目的の位置までseekしてfgets)という、なんとも、納得の
いかない対応でした。現実から逃げてるだけじゃん。
Perlでも同様の対応を行う事で、更に向上できそうです。
この場合、ダイレクトIO関数を利用した方がいいんですかね?
http://www.php.net/dio
他に良い方法があれば、教えて下さい(DBは考えない方向で)。
後、
$Str = fgets( $PTR, 1000 )
$Str = fgets( $PTR, 100000 )
とかも、結構(確認した時は5秒くらい)差が出ますね。
前に行き過ぎた分だけ、つじつまあわせの為に、戻っているような感が
あります。気のせいかもしれません。
PHPのバージョン:4.3.5RC4
[データの構造]
キー(昇順でソート済み),データ1,データ2,データ3
...
...
...
以下延々と続く。
確認は下記の様なプログラムで行いました。
ファイルオープン・クローズの部分は割愛しています。
---------------------------------------------------------------------
Perl : 0.25 Sec
---------------------------------------------------------------------
my $Key = "99999999";
my $Code = "";
while(<INFILE>)
{
$Code = substr( $_, 0, length( $Key ) );
if( $Code eq $Key )
{
print $_;
last;
}
if( $Key < $Code ){ last; }
}
---------------------------------------------------------------------
PHP : 0.83 Sec
---------------------------------------------------------------------
$Key = "99999999";
$Code = "";
while( $Str = fgets( $PTR, 1024 ) )
{
$Code = substr( $Str, 0, strlen( $Key ) );
if( $Code === $Key )
{
echo $Str;
break;
}
if( $Key <= $Code ){ break; }
}
---------------------------------------------------------------------
--
Seiji Masugata<s.masugata @ digicom.dnp.co.jp>
PHP-users メーリングリストの案内