自分の興味の赴くままにIT技術系のネタを取りとめもなくメモっています。
Ruby言語やLinuxのネタが多いです。
Ruby言語やLinuxのネタが多いです。
March 31, 2002 [おもひで]
s = Time.new
def fortune(file)
res = ""
line = ""
IO.readlines(file, "\n%\n").each do |line|
res = line if rand($.) < 1
end
res = line if res == ""
res = $2 if res =~ /^(%\n)?(.*)\n%\s*\n?$/m
res
end
puts fortune(ARGV[0]) #(1)
#(0..1000).each { fortune(ARGV[0]) }
#p Time.new - s
■ 2つ実装ができたので、どっちが速いのかなぁというわけで時間を図ってみることに(上記のコードの#の部分を有効にして(1)をコメント化)。ascii-artというfortune辞書を10倍にしたファイルを作ってみた。
$ruby test.rb ascii-art-10-times.txt 6.033442
■ 対するは、今のfortuneのコードの簡略化版
s = Time.new
def fortune(path)
open(path) do |file|
lines = file.read.split(/%\n/)
lines[rand(lines.size)]
end
end
(0..1000).each { fortune(ARGV[0]) }
p Time.new - s
■ んで、結果。
$ruby fortune-lite.rb ascii-art-10-times.txt 1.542972
■ あり?今のコードの方が速い....。なんか間違ってんのかな?
教えていただいたコードって、rand($.)でマッチしてもbreakしたらダメなんですよね?
■ うーむ...。どうも、IO.readlines()が遅いみたい。以下のコードを試してみる。
s = Time.new
def fortune(file)
IO.readlines(file, "\n%\n").each do |line|
end
end
(0..1000).each { fortune(ARGV[0]) }
p Time.new - s
$ruby test2.rb ascii-art-10-times.txt 5.926064
■ 考えてみたらあり得ない結果とはいえなくもない気がしないでもない(ってどっちだ?(^^;))。ARGF.getsだともうちょっと速いのかな?
s = Time.new
def fortune(file)
ARGF.each do |line|
end
end
(0..1000).each { fortune(ARGV[0]) }
p Time.new - s
■ あり?これ、1回、ARGFがEOFまで読み込まれた後、反応しなくなってしまう。なんでだろう。そういうモノなのかな? ま、いっか。疲れたし(^^;)。
■ おっと、忘れてた。オレの環境はLinux-2.4.18 / ruby 1.7.2 (2002-01-05)[i686-linux]、試したfortune辞書のサイズは59040byte, 1540行だ。
■ ちなみに、いろいろやっている間、先頭が%から始まるfortune辞書では、空文字が返されるバグを見つけた。明日にでも直すか...。

単純に rand 呼ばれる回数くらべてもらくだ本のアルゴリズムの方が多いんで.<br>あれは時間計算量ではなく空間計算量を押さえる手法です.入力ファイルがど<br>んなに大きくてもメモリ上に置くのは高々二レコード分だけですむという.<br><br>メモリが足りているっていう前提があるのならまとめて読んだ方が簡単で高速<br>なのは間違い無いです.<br><br>read して split するのと readlines するのとでどっちがはやいのかは知らな<br>いなぁ....
XREA + tDiary + Namazuのマニュアルにある.namazurcの編集の編集ですが<br><br>Replace /home/hoge/tdiary/html/(\d\d\d\d)/ http://hoge.s1.xrea.com/t/?date=\1<br><br>homeのところはvirtualではないですかね?
> ruby -v<br> ruby 1.6.5 (2001-09-19) [sparc-solaris2.6]<br> > time ruby -e '100.times {File.open("/usr/dict/words"){|inf| inf.readlines("\n")}}'<br> ruby -e '100.times {File.open("/usr/dict/words"){|inf| inf.readlines("\n")}}' 16.46s user 0.23s system 99% cpu 16.728 total<br> > time ruby -e '100.times {File.open("/usr/dict/words"){|inf| inf.read.split("\n")}}'<br> ruby -e '100.times {File.open("/usr/dict/words"){|inf| inf.read.split("\n")}} 12.09s user 0.28s system 100% cpu 12.370 total<br><br>....っていうことで read して split の方がはやいみたい.<br>あくまで全部一辺に読む場合は,だけど.
kjanaさん:追試どうもです。今回はメモリのサイズも気にするほどでもないと思いますので、前のアイデアのままで行こうと思います。<br>恵司さん:おっしゃるとおりです。どうもです。今夜直しておきます。