The calendar is gone.
Click here to view posts


Sort vs sort!
I remembered reading a comment Matz made once about the ! methods. It went something like "! methods are destructive and should only be used when performance is needed". I found a benchmark example that show sort vs sort! speeds are depended on the garbage collection[1]. Today I was reading a chunk of ruby-prof code and found the comment.
#from RubyProf::GraphHtmlPrinter 
def calculate_thread_times
  # Cache thread times since this is an expensive
  # operation with the required sorting      
  @result.threads.each do |thread_id, methods|
    top = methods.sort.last
    
    thread_time = 0.01
    thread_time = top.total_time if top.total_time > 0

    @thread_times[thread_id] = thread_time 
  end
end   

I rewrote the code with a sort! in my head but wonder would it really have any affects on the time? A little context for test. I just used ruby-prof in an around filter in the application.rb file for a rails project. The html file that ruby-prof produces is not small and includes parts of the rails framework, mysql library, and core ruby code.
require "benchmark"
def calculate_thread_times!(result)
     thread_times={}
     result.threads.each do |thread_id, methods|
        methods.sort!
        thread_time = methods.last.total_time > 0 ? methods.last.total_time : 0.01
        thread_times[thread_id] = thread_time
     end
end
def calculate_thread_times(result)
  # Cache thread times since this is an expensive
  # operation with the required sorting
  thread_times ={}
  result.threads.each do |thread_id, methods|
    top = methods.sort.last
    thread_time = 0.01
    thread_time = top.total_time if top.total_time > 0
    thread_times[thread_id] = thread_time
  end
end

Benchmark.bm(12) do |test|
  test.report("no_bang:")    do
	 lresult = result
	 calculate_thread_times(lresult)
  end
  test.report("bang:") do
	 lresult = result
	 calculate_thread_times!(lresult)
  end
end

#                  user     system      total        real
#no_bang:      0.010000   0.000000   0.010000 (  0.006786)
#bang:         0.000000   0.000000   0.000000 (  0.004242)
Clearly not enough improvement to stop caching thread times but, now the methods are in order. We could stop caching and access the thread time like
@result.threads[thread_id].last
#I think
Since the calculate_thread_times is called when you create a new RubyProf::GraphHtmlPrinter you should never need to call sort again. For example in the ERB template. I did find that using Benchmark.bmbm cause the real values to be swapped just like in the rdoc example[1].

I just submitted a patch to the ruby prof ruby forge group[2]. It is not a big improvement over all. Using my numbers above the current GraphHtmlPrinter use 0.013572 just for sorting. It should now only take 0.004242. Saving the world most a second....

[1] http://www.ruby-doc.org/core/classes/Benchmark.html
[2] http://rubyforge.org/tracker/index.php?func=detail&aid=16364&group_id=1814&atid=7062