From: George Ogata Date: 2006-03-11T11:13:44+09:00 Subject: Re: Help me understand why the Ruby block is slower than wit Alan Burch writes: >> File.open("wordlist") { |f| >> while w = f.gets >> puts w if w.size==11 && w.split(//).uniq.size == 11 >> end >> } > > Ok, factor of 10 faster, and more Ruby like, much and many Thanks! > Others, any comments on the block slow down? I don't see much of a slowdown. ---------------------------------------------------------------------- g@crash:~/tmp$ cat read-slow.rb File.open("./words") { |f| while f.gets if $_.length == 11 ar = $_.split(//) if ar.uniq! == nil print "#{ar.to_s}" end end end } g@crash:~/tmp$ /usr/bin/time ruby read-slow.rb > out-slow 2.56user 0.01system 0:02.64elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+550minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-slow.rb > out-slow 2.55user 0.01system 0:02.57elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+550minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-slow.rb > out-slow 2.54user 0.01system 0:02.56elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+550minor)pagefaults 0swaps g@crash:~/tmp$ cat read-fast.rb f = File.open("./words") begin while f.gets if $_.length == 11 ar = $_.split(//) if ar.uniq! == nil print "#{ar.to_s}" end end end rescue EOFError f.close end g@crash:~/tmp$ /usr/bin/time ruby read-fast.rb > out-fast 2.51user 0.01system 0:02.54elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+544minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-fast.rb > out-fast 2.50user 0.01system 0:02.56elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+544minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-fast.rb > out-fast 2.51user 0.01system 0:02.53elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+544minor)pagefaults 0swaps ---------------------------------------------------------------------- There's a bit of a slowdown, but note that in your "fast" algo, the stream is never closed, since IO#gets never throws EOFError. Do `ri IO#gets' for the method's documentation. :-) Another speedup: replace: w.split(//).uniq.size == 11 with: w !~ /(.).*\1/ It's faster since there's less intermediate diddlage, but theoretically it shouldn't scale as well. You'd have to increase your "11" quite a lot to notice it though I think. More shell dump. ---------------------------------------------------------------------- g@crash:~/tmp$ cat read-one.rb File.open("words") { |f| while w = f.gets puts w if w.size==11 && w.split(//).uniq.size == 11 end } g@crash:~/tmp$ /usr/bin/time ruby read-one.rb > out-one 2.54user 0.02system 0:02.57elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+548minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-one.rb > out-one 2.54user 0.01system 0:02.56elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+548minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-one.rb > out-one 2.55user 0.01system 0:02.58elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+548minor)pagefaults 0swaps g@crash:~/tmp$ cat read-two.rb File.open("words") { |f| while w = f.gets puts w if w.size==11 && w !~ /(.).*\1/ end } g@crash:~/tmp$ /usr/bin/time ruby read-two.rb > out-two 1.23user 0.01system 0:01.25elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+713minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-two.rb > out-two 1.27user 0.01system 0:01.29elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+713minor)pagefaults 0swaps g@crash:~/tmp$ /usr/bin/time ruby read-two.rb > out-two 1.27user 0.02system 0:01.30elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+713minor)pagefaults 0swaps g@crash:~/tmp$ g@crash:~/tmp$ g@crash:~/tmp$ diff out-one out-two g@crash:~/tmp$ ----------------------------------------------------------------------