From: Brian Adkins Date: 2007-10-15T05:35:07+09:00 Subject: Re: top 10 last played mp3's On Oct 14, 7:03 am, "Andreas S." wrote: > Brian Adkins wrote: > > On Oct 13, 8:35 pm, "Andreas S." wrote: > I'd be careful with all these optimizations you are suggesting. By far > the slowest part is the recursive traversal of the directory, and you > can't speed that up. Array#reverse is in a completely different league > and not worth optimizing if you have to sacrifice readability. The > File.atime calls are pretty fast, too (100.000 per second on my old > powerbook). You're correct, my bad. Thanks for bringing that to my attention. 1) The speed difference between Dir (good) and Find (terrible) totally dominates. Never underestimate the slowness of Ruby code compared to C code running in the interpreter :) 2) Phrogz is correct regarding Enumerable#sort_by. Since it builds an array of tuples first, File.atime is only called once per path. I was influenced by misapplying the warning in the pickaxe, but in this case, sort_by seems warranted since I was basically doing the same thing (building an array of tuples with the sort value) manually - but in Ruby instead of C! In fact, if I had bothered to turn the page, the example they give is strangely relevant! 3) Array#reverse is just noise in the profile below, so I should be more careful about avoiding it. 4) Sorry Robin, your praise was premature :) On minor point; I think you may be mistaken regarding the slowest part being the directory traversal (at least in your code). Both the sorting and time comparison are much greater: brian@imagine:~/sync/code/ruby$ ruby -r profile andreas.rb % cumulative self self total time seconds seconds calls ms/call ms/call name 43.42 1.32 1.32 2 660.00 1385.00 Enumerable.sort_by 28.95 2.20 0.88 26958 0.03 0.03 Time#<=> 12.50 2.58 0.38 4 95.00 142.50 Array#each 7.89 2.82 0.24 2 120.00 120.00 Dir#[] 6.25 3.01 0.19 5220 0.04 0.04 File#atime 0.99 3.04 0.03 2 15.00 25.00 Kernel.require 0.00 3.04 0.00 10 0.00 0.00 Module#class_eval 0.00 3.04 0.00 9 0.00 0.00 Kernel.singleton_method_added 0.00 3.04 0.00 3 0.00 0.00 Module#included 0.00 3.04 0.00 1 0.00 0.00 Module#module_function 0.00 3.04 0.00 8 0.00 0.00 Class#inherited 0.00 3.04 0.00 77 0.00 0.00 Module#method_added 0.00 3.04 0.00 3 0.00 0.00 Module#include 0.00 3.04 0.00 1 0.00 3010.00 Integer#times 0.00 3.04 0.00 1 0.00 0.00 Module#attr_accessor 0.00 3.04 0.00 3 0.00 0.00 Module#append_features 0.00 3.04 0.00 1 0.00 0.00 Module#private 0.00 3.04 0.00 5 0.00 0.00 Module#attr_reader 0.00 3.04 0.00 2 0.00 0.00 Array#[] 0.00 3.04 0.00 2 0.00 0.00 String#== 0.00 3.04 0.00 2 0.00 0.00 Array#reverse -0.00 3.04 -0.00 2 -0.00 1505.00 Object#n_recent_files 0.00 3.04 0.00 1 0.00 3040.00 #toplevel You were correct in my case though since I used the Find library: % cumulative self self total time seconds seconds calls ms/call ms/call name 34.05 45.03 45.03 57436 0.78 2.08 Kernel.catch 23.39 75.96 30.93 16019 1.93 2.79 Dir#each 5.66 83.44 7.48 16019 0.47 0.47 Dir#open 5.34 90.50 7.06 220364 0.03 0.03 String#== 5.27 97.47 6.97 1 6970.00 128230.00 Find.find 3.71 102.38 4.91 57437 0.09 0.13 Kernel.dup 1.87 104.85 2.47 1 2470.00 3820.00 Array#sort! 1.79 107.22 2.37 57435 0.04 0.04 File#join 1.76 109.55 2.33 57435 0.04 0.04 Array#unshift 1.72 111.83 2.28 57437 0.04 0.04 String#initialize_copy 1.63 113.99 2.16 57436 0.04 0.04 File#exist? 1.60 116.10 2.11 57436 0.04 0.04 File#file? 1.54 118.14 2.04 57435 0.04 0.04 Kernel.untaint 1.42 120.02 1.88 57431 0.03 0.03 File#lstat 1.28 121.71 1.69 57431 0.03 0.03 File::Stat#directory?