I think everyone is enjoy ruby's programming, the meta programming is really efficiently way. But sometime we meet our function or app have a poor performance.
Guess what, my first through was, ruby is f**k too slow.. , but my second through was, how can I figure out where is slow, rather than switch some other language?
So let's start some profiling to figure it out.
add this in your Gemfile or gem install it.
gem 'ruby-prof', :git => 'git://github.com/ruby-prof/ruby-prof.git', :group => [:development, :test]
Add this function in your ApplicationController.rb
def profile(prefix = "profile") result = RubyProf.profile { yield } dir = File.join(Rails.root, "tmp", "performance", params[:controller].parameterize) FileUtils.mkdir_p(dir) file = File.join(dir, "callgrind.%s.%s.%s" % [prefix.parameterize, params[:action].parameterize, Time.now.to_s.parameterize] ) open(file, "w") {|f| RubyProf::CallTreePrinter.new(result).print(f, :min_percent => 1) } end helper_method :profile
You can put what you want profile in this block, and it will generate callgrind file under your tmp/performance/[controller-name] folder.
If you're under mac, you can install this tool to check the function profiling:
brew install qcachegrind
other platform have some equal tools like, kcachegrind under linux.
you will got the profile result like this picture.
Hope this will help you figure out which part is cause the performance issue.
And my other little trick is, like the :profile helper, I add a simple timer helper:
def timer(tag = "default") t1 = Time.now yield t2 = Time.now msecs = (t2 - t1) * 1000.0 logger.info "Time in profile #{tag} #{msecs.to_i} ms" end helper_method :timer
Together with code block, you can get each part 's timer profile like below:
timer("total") do timer("func1") do function1 end function2 timer("loop") do some_array.each { function } end end
Seems too naive, but this simple method can be more helpful than other complex tools.