Paluy on Miscellaneous

Of course I'm an optimist - I don't see much point in being anything else. - Winston Churchill

Profiling Rails Applications

Your finaly got clients and everything works fine.

But users expect several performance issues.

How can I profile my Ruby on Rails application?

Available Tools

GC::Profiler

The GC profiler provides access to information on GC runs including time, length and object space size.

1
2
3
4
5
6
7
8
GC.start # clear GC before profiling
GC::Profiler.enable

# your code

GC.start
puts GC::Profiler.report
GC::Profiler.disable

Ruby Benchmark

Ruby has core module to Benchmark your code. It helps you to mesure running time of your code.

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'benchmark'

Benchmark.bm do|b|
  b.report("+= ") do
    a = ""
    500_000.times { a += "." }
  end

  b.report("<< ") do
    a = ""
    500_000.times { a << "." }
  end
end

I suggest you to add benchmark_suite gem. There is a set of enhancements to the standard library benchmark.rb

ObjectSpace

ObjectSpace class already described in previous post. You should also check Visualizing memory leaks in Ruby using ObjectSpace methods.

RUBY-PROF

How to use in Rails:

  • Add the ruby-prof to your gemfile
1
2
3
group :profile do
  gem 'ruby-prof'
end

Note: verify your /config/environments/profile.rb has the following settings:

1
2
config.cache_classes = true
config.cache_template_loading = true
  • Add rack adapter to config.ru:
1
2
3
if Rails.env.profile?
  use Rack::RubyProf, :path => '/temp/profile'
end

Note: By default the rack adapter will generate a html call graph report and flat text report. You can add printer option as following:

1
use Rack::RubyProf, :path => '/temp/profile', :printers => {RubyProf::GraphHtmlPrinter => 'graph.html'} # or any other printer as described

More printers options can be found here

  • Add Profile to your code:
1
2
3
4
5
6
7
8
9
# define mesurment type
# as described: https://github.com/ruby-prof/ruby-prof#measurements
RubyProf.measure_mode = RubyProf::PROCESS_TIME

RubyProf.start

# code to profile

result = RubyProf.stop

Perftools.rb

While ruby-prof is a good tool, I, personally, prefere to use perftools.rb. It also has a rack gem.

The main advantage of perftools: it samples your process using setitimer() so it can be used in production with minimal overhead.

How to use in Rails:

  • Add the rack-perftools_profiler to your gemfile
1
gem 'rack-perftools_profiler', :require => 'rack/perftools_profiler'
  • Add middleware to config/environment.rb:
1
config.middleware.use ::Rack::PerftoolsProfiler, :default_printer => 'pdf', :bundler => true

See more options here.

  • Profile your application
1
2
3
curl http://localhost:3000/__start__
curl http://localhost:3000/__stop__
curl http://localhost:3000/__data__

Visualization of your report

  • ruby-prof and perftools.rb has support for different output formats. One of them is KCacheGrind
  • In Ruby 2 you can gather your stack traces. Read more here

Summary

  • Remember: More Objects => Longer GC => Slow application
  • Always examine your HEAP
  • Use Tools!

Comments