新規記事投稿 フォロー記事投稿 記事のキャンセル
From: にあ <nir@mxa.meshnet.or.jp>
Subject: Re: 文字列の置換
Date: 1997/01/21 23:26:42
Reference: mesh.program/00191

1月21日に、Hiroさんは書きました。

>tieってなんでしょう?初耳です。dieみたいなもの・・・じゃないですよね。^^;
>
あたしも New Camel Book はこの間買ってきたばかりで、あまりチャンと読んで
ないのですが (^^;; 変数を packageクラスにバインドするもののようです。
DBM ファイルを扱う時には、%変数をファイル名(やその他のパラメータとともに)
DB_File (あるいは NDBM_File, GDBM_File, SDBM_File, ODBM_File のいずれかの)
クラスにバインドする事になります。

perl4 までで使われてきた dbmopen() を呼び出すと、perl5 ではそれを tie に
差し替えて実行するようです。つまり dbmopen() は単に以前の版との互換性のため
だけに残されたみたいですね。

いままで、DBM ファイルは perl からチャンとロックする方法が無かったのですが
tie を使えばバインドされたクラスから file descriptor を参照して open() する
事により flock() する事が可能になったので安全になりました。
# とか、書いていますが、まだ、実際にコーディングしたことは無いので... (^^;;
# New Camel Book の p.392〜 を参照して下さい。

>あと、read関数でファイルの全内容を読み出すときは、第三パラメータには
>どういう指定をすればいいんでしょうか?
>巨大な数字を指定すれば読める分だけ読んでくれるようですが、それじゃあちょっと美しくないんで。
>$_ = join(' ',<FOO>);
>よりは、readの方が速そうなんで。
>
基本的には単にバッファエリアですから適当な大きさがあれば良いのでしょうけど
チョット興味もあったので調べてみました。
以下のようなスクリプトで、/large/text/file の大きさは約10MBで測定して見ました。
環境は HP-UX の載っている PA-RISC で、メモリは100MB入れてますがクロックは
33MHz です。(^^;; perl のヴァージョンは 5.003 です。

何回か計って数値が変わらなくなった後なので、ファイルは完全にキャッシュされて
いると思われます。

#!/usr/local/bin/perl

for ($i = 1; $i <= 5; $i++) {
        printf("%dth iteration: ", $i);
        open(INFILE, "/large/text/file");
        $_ = $ARGV[0];
        undef($a);
        if (/0/) {$a = join('', <INFILE>)}
        if (/1/) {while (<INFILE>) { $a .= $_; }}
        if (/2/) {while (read(INFILE, $_, 8192)) { $a .= $_; }}
        if (/3/) {while (sysread(INFILE, $_, 1024)) { $a .= $_; }}
        if (/4/) {while (sysread(INFILE, $_, 2048)) { $a .= $_; }}
        if (/5/) {while (sysread(INFILE, $_, 4096)) { $a .= $_; }}
        if (/6/) {while (sysread(INFILE, $_, 8192)) { $a .= $_; }}
        if (/7/) {while (sysread(INFILE, $_,16384)) { $a .= $_; }}
        if (/8/) {while (sysread(INFILE, $_,32768)) { $a .= $_; }}
        if (/9/) {while (sysread(INFILE, $_,65536)) { $a .= $_; }}
        printf("%dbyte\n", length($a));
        close(INFILE);
}
printf("%dsec\n", time - $^T);

exit(0);

パラメータを 0〜9 まで変えて計ったところこの様な結果になりました。

0: 65sec, 1: 61sec, 2: 29sec, 3: 41sec, 4: 32sec,
5: 29sec, 6: 26sec, 7: 28sec, 8: 29sec, 9: 34sec

一行ずつ連結していくより一気に配列に読んで join() した方が速いかと思って
いたので、チョット意外でした。まあ、それでも read() した方が断然速いのは
当たり前ですね。sysread() はもっと速いかと思っていたのですが、read() と
大して変わらなかったです。バッファエリアは小さすぎず大きすぎず、中庸が
良いと言うことで、まあ、順当な結果ではないでしょうか。(^^)

# これはあくまで、あたしの所でこうなったと言うだけで、環境が変われば最適値も
# 変わるでしょうから、バッファサイズをあまり気にすることは無いと思います。

>#今、Programming Perlは発注中なんですよね。
>
早く来ると良いですね。(^^)