You can use the left and right arrow keys to navigate this presentation.

"The Website's Slow"

Tips and Tools for Identifying Performance Bottlenecks

Who I am

And why you should listen to me

My name is Sammy Larbi

I'm a freelance Ruby developer

6 years playing with Rails

4 projects recently needed P.E.D.

(Performance Enhancing Development)

Interrupt Me

"The Website's Slow"

The customer tells you 'The website is slow'
You respond, asking which webpage

Isolated Actions

n+1 queries in an action
slow query in an action

Or maybe your app resides on one network and your DB on another, and you're doing

select * from a_table

with many records & a ton of

BLOB

columns you have to transfer

Measurement



Data Anonymity

Visibility

rails-footnotes

Example of information rails-footnotes provides.

rails-footnotes @ github

bullet

Example of information the bullet gem provides.

bullet @ github

rack-insight

rack-insight @ github

Granularity

ruby-prof

Example of information ruby-prof provides in the call tree printer.
ruby-prof @ github example jruby's got you covered

ruby-prof

entire action

gem 'ruby-prof', groups: [:development, :profile] # in Gemfile
if Rails.env.profile? # in config.ru
  use Rack::RubyProf, :path => '/temp/profile'
end
# profile db connection settings in config/database.yml
# (same as dev environment is fine)
# Create config/environments/profile.rb with at least these options:
config.cache_classes = true
config.cache_template_loading = true
# bundle install and restart with: rails s -e profile
code from ruby-prof @ github

ruby-prof

specific lines of code

result = RubyProf.profile do
  ...
  [code to profile]
  ...
end

printer=RubyProf::GraphPrinter.new(result)
printer.print(STDOUT, {})
code from ruby-prof @ github

benchmark

Benchmark.bm do |x|
  x.report("find by id: ") { 
    @student = Student.find_by_id(params[:student_id]) 
  }
  
  x.report("find: ") { 
    @student = @district.students.find(params[:student_id]) 
  }
end
    
       user     system      total        real
find by id:   0.090000   0.000000   0.090000 (  1.352654)
find:   0.030000   0.000000   0.030000 (  0.030710)
    
benchmark docs

Further Investigation

perftools.rb

(example output)

rails performance testing

The customer tells you 'The website is slow'
You respond, asking which webpage
The customer says 'everywhere'

Server Issues

Memory

top

output of command: top (highlighting the swap memory in use)

free

output of command: free (highlighting the swap memory in use)

Per process:

ps aeux --sort=-vsz output of command: ps aeux --sort=-vsz

puma

Uses

threads

instead of worker processes
i.e., how a web server is supposed to work
-Wes Gamble
puma @ github

puma

Use JRuby or Rubinius to take full advantage
# in config/environments/production.rb
config.threadsafe!
puma @ github

CPU


# processor cores available / avg load time (s/page) * 60 (s/min)
=>

max throughput in pages per minute

Server Level Stats

For your investigation:

visage & collectd

visage website collectd website

Holistic View

request‑log‑analyzer

example output from request-log-analyzer
example output r-l-a wiki @ github

new relic

example of a New Relic Graph

Run your own

rails_metrics vs. system-metrics

Unmaintained?

ActiveSupport::Notifications

ActiveSupport::Notifications.instrument("render", :extra => :information) do
  render :text => "Foo"
end

ActiveSupport::Notifications.subscribe("render") do |*args|
  events << ActiveSupport::Notifications::Event.new(*args)
end
ActiveSupport::Notifications docs

harness
&
statsd

harness @ github statsd @ github
example of a StatsD Graph

statsd requirements

  • needs nodejs
  • graphite
  • which needs django, carbon, and other packages
  • which all run on python

epic yak shaving

Yak shaving
image from snapperwolf @ flickr
example of a StatsD Graph

This Needs To Be Easier

But I don't have all the answers yet

Who ever said hardware was cheaper than programmers?

OMG Thanks!