SlideShare a Scribd company logo
Profiling and monitoring
        ruby/rails

        JÁN SUCHAL
         @JSUCHAL
Optimalization

 “If you can’t measure it, you can’t improve it.” – Lord Kelvin
 Environment
   development vs. production (hw, sw, load)
   data (synthetic vs. real)
 Bottlenecks
   10sec * 1 run vs. 0.5s * 100 runs
   run time * runs vs. development time
 Microbenchmarks
   waste of time vs. 20 * 1% = 20%
 “There are three kinds of lies: lies, damned lies, and statistics.” –
  Benjamin Disraeli
     single run vs. multiple runs
     average vs. standard deviance, percentiles
     cold vs. hot cache
Profiler - Example

# profiler/dates.rb

require 'date'

def create_days_after(date_str, n)
  after = Date.strptime(date_str) + n
  after.strftime("%Y-%m-%d")
end

1000.times do
  create_days_after("1982-10-27", 5)
end
Ruby Profiler

 $ gem install ruby-prof
 $ ruby-prof dates.rb
   How long does each method take?

 $ ruby-prof dates.rb –m 3
   Just methods above 3% time

  Thread ID: 7749480
  Total: 0.653076

  %self     total      self   wait   child    calls   name
  12.97      0.19      0.08   0.00    0.18     2000   String#scan
  11.57      0.08      0.08   0.00    0.00   205000   String#===
   6.87      0.18      0.04   0.00    0.14     1000   String#gsub
   6.28      0.05      0.04   0.00    0.01    14000   Hash#values_at
   4.08      0.03      0.03   0.00    0.00    80470   Hash#default
   3.21      0.03      0.02   0.00    0.01     3000   Date#emit
Ruby Profiler

Thread ID: 7749480
Total: 0.653076

%self     total      self    wait   child    calls   name
12.97      0.19      0.08    0.00    0.18     2000   String#scan
11.57      0.08      0.08    0.00    0.00   205000   String#===
 6.87      0.18      0.04    0.00    0.14     1000   String#gsub
 6.28      0.05      0.04    0.00    0.01    14000   Hash#values_at
 4.08      0.03      0.03    0.00    0.00    80470   Hash#default
 3.21      0.03      0.02    0.00    0.01     3000   Date#emit

 total – time in method and children calls
 self – time in method call
 wait – wait time
 child – time in child calls
 call – number of times method invoked
Ruby Profiler

 $ ruby-prof dates.rb -m 3 -p graph
   Which method calls what and how many times?

Thread ID: 15523700
Total Time: 0.675587048

%total    %self    total   self    wait   child           calls   Name
                   0.20    0.10    0.00   0.20        2000/2000   <Class::Date>#_strptime_i
30.28%   14.70%    0.20    0.10    0.00   0.20             2000   String#scan
                   0.04    0.04    0.00   0.00    110000/205000   String#===
                   0.02    0.01    0.00   0.01        3000/5000   Date::Format::Bag#method_...
                   0.02    0.00    0.00   0.01        2000/3005   Class#new
                   0.01    0.01    0.00   0.00        5000/5000   String#sub!
                   0.01    0.00    0.00   0.01        2000/2000   Range#===
                   0.00    0.00    0.00   0.00        3000/3000   String#to_i
                   0.00    0.00    0.00   0.00        2000/2000   <Class::Regexp>#quote
                   0.00    0.00    0.00   0.00        2000/2000   Regexp#===
                   0.00    0.00    0.00   0.00        1000/1000   <Class::Date>#num_pattern?
                   0.00    0.00    0.00   0.00        1000/2000   <Class::Date>#_strptime_i
Ruby Profiler

Thread ID: 15523700
Total Time: 0.675587048

%total    %self    total   self    wait   child           calls   Name
                   0.20    0.10    0.00   0.20        2000/2000   <Class::Date>#_strptime_i
30.28%   14.70%    0.20    0.10    0.00   0.20             2000   String#scan
                   0.04    0.04    0.00   0.00    110000/205000   String#===
                   0.02    0.01    0.00   0.01        3000/5000   Date::Format::Bag#method_..



 three parts
   parent calls
   method

   children calls

 calls – number of calls from method/total number of calls
Ruby Profiler

 $ ruby-prof dates.rb -p graph_html -m 3 > graph.html
 $ ruby-prof dates.rb -p graph_html -m 3 –s self > graph.html
Profiler - KCacheGrind

 $ ruby-prof dates.rb -p call_tree -m 3 > dates1.grind
 $ kcachegrind dates1.grind
benchmark-ips

 require   'benchmark/ips'
 require   'ostruct'
 require   'hashr'
 require   'hashugar'

 SMALL_HASH = {:a => 1, :b => 2}

 Benchmark.ips do |x|
   x.report 'OpenStruct create small hash and access once', 'OpenStruct.new(SMALL_HASH).item5'
   x.report 'Hashr create small hash and access once', 'Hashr.new(SMALL_HASH).item5'
   x.report 'Hashugar create small hash and access once', 'Hashugar.new(SMALL_HASH).item5‘
 end


OpenStruct create small hash and access once
  43858.0 (±5.5%) i/s - 221820 in 5.074250s (cycle=3697)
Hashr create small hash and access once
  67408.9 (±5.0%) i/s - 339780 in 5.053728s (cycle=5663)
Hashugar create small hash and access once
 230217.9 (±4.2%) i/s - 1152670 in 5.015705s (cycle=15790)
Memory profiling

 Patched ruby
 $ rvm install 1.9.3 --patch railsexpress --name gc
 $ ruby-prof --mode=allocations dates.rb –m 3


%self      total      self   wait     child   calls   name
59.23    6004.00   6004.00   0.00      0.00    1000   <Class::Date>#strptime
 9.87    1000.00   1000.00   0.00      0.00    1000   Date#strftime
 9.87    9004.00   1000.00   0.00   8004.00    1000   Object#create_days_after
 9.87    1000.00   1000.00   0.00      0.00    1000   Date#+
 9.87   10004.00   1000.00   0.00   9004.00       1   Integer#times
Rails / NewRelic Developer mode

 gem 'newrelic_rpm‘
 http://localhost:3000/newrelic
 gem 'newrelic_rpm', git:
 'git://github.com/jsuchal/rpm.git',
 branch: 'feature-profile-sorting'
NewRelic Developer mode
Rails / NewRelic Developer mode
NewRelic Developer mode
NewRelic Developer mode Profiler
Custom Method Tracers

# initializers/elastic_search_traces.rb

require 'new_relic/agent/method_tracer‘

ElasticSearch.class_eval do
  include NewRelic::Agent::MethodTracer

  add_method_tracer :search, 'Custom/elasticsearch/search'
  add_method_tracer :index, 'Custom/elasticsearch/index'
end
NewRelic Production Monitoring

 Web Transactions – controller actions drilldown
 Transaction Traces – detailed slow requests
 Slow SQL – slow queries
 Background job monitoring
 Availabality monitoring
 Deployment tracking
 Scalability analysis
 ...
 Server monitoring (load, disks, …)
Profiling and monitoring ruby & rails applications
Profiling and monitoring ruby & rails applications
Profiling and monitoring ruby & rails applications
Profiling and monitoring ruby & rails applications
Error tracking

 ExceptionNotifier
 www.airbrake.io
Most common performance problems

 “1 + N query problem”
   joins FTW!

 Lack of proper indexing
 Unnecessary ActiveRecord loading
   e.g. count vs. size vs. length

 Default GC parameters
    37signals params
    RUBY_HEAP_MIN_SLOTS=600000 # This is 60(!) times larger than default
    RUBY_GC_MALLOC_LIMIT=59000000 # This is 7 times larger than default
    RUBY_HEAP_FREE_MIN=100000 # This is 24 times larger than default

 Unknown abstraction internals
   e.g. OpenStruct

More Related Content

PDF
Tt subtemplates-caching
TXT
Xmpp prebind
PDF
From mysql to MongoDB(MongoDB2011北京交流会)
PDF
Mongodb debugging-performance-problems
PDF
Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
PDF
Cache is King - RailsConf 2019
PDF
Solr @ Etsy - Apache Lucene Eurocon
PDF
Solr & Lucene @ Etsy by Gregg Donovan
Tt subtemplates-caching
Xmpp prebind
From mysql to MongoDB(MongoDB2011北京交流会)
Mongodb debugging-performance-problems
Eric Redmond – Distributed Search on Riak 2.0 - NoSQL matters Barcelona 2014
Cache is King - RailsConf 2019
Solr @ Etsy - Apache Lucene Eurocon
Solr & Lucene @ Etsy by Gregg Donovan

What's hot (18)

PDF
7주 JavaScript 실습
PPTX
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
PDF
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
PDF
Debugging: Rules And Tools - PHPTek 11 Version
PDF
StHack 2013 - Florian "@agixid" Gaultier No SQL injection but NoSQL injection
PDF
Teaching Your Machine To Find Fraudsters
PDF
Nagios Conference 2013 - Sheeri Cabral - Alerting With MySQL and Nagios
PDF
Living with garbage
KEY
Building Better Applications with Data::Manager
PDF
Nodejs mongoose
PPT
Php Mysql
PDF
How to stand on the shoulders of giants
PDF
node.js Module Development
PDF
rsyslog v8: more than just syslog!
PPTX
19. CodeIgniter imagini in mysql
PPT
Mocking Dependencies in PHPUnit
KEY
(Parameterized) Roles
7주 JavaScript 실습
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
Debugging: Rules And Tools - PHPTek 11 Version
StHack 2013 - Florian "@agixid" Gaultier No SQL injection but NoSQL injection
Teaching Your Machine To Find Fraudsters
Nagios Conference 2013 - Sheeri Cabral - Alerting With MySQL and Nagios
Living with garbage
Building Better Applications with Data::Manager
Nodejs mongoose
Php Mysql
How to stand on the shoulders of giants
node.js Module Development
rsyslog v8: more than just syslog!
19. CodeIgniter imagini in mysql
Mocking Dependencies in PHPUnit
(Parameterized) Roles
Ad

Similar to Profiling and monitoring ruby & rails applications (20)

PDF
performance vamos dormir mais?
PDF
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
ODP
Beyond PHP - It's not (just) about the code
PDF
Sinatra and JSONQuery Web Service
ODP
Beyond PHP - it's not (just) about the code
PDF
Rails Performance
ODP
Dynamic Tracing of your AMP web site
PDF
Top Node.js Metrics to Watch
ODP
Performance Optimization of Rails Applications
ODP
Beyond PHP - it's not (just) about the code
PDF
Практический опыт профайлинга и оптимизации производительности Ruby-приложений
DOCX
Ruby on Rails Developer - Allerin
PDF
Distributed Load Testing with k6 - DevOps Barcelona
PDF
Distributed load testing with K6 - NDC London 2024
PDF
Hidden Gems of Ruby 1.9
KEY
fog or: How I Learned to Stop Worrying and Love the Cloud
PPT
Ruby on Rails Intro
PDF
Javascript Memory leaks and Performance & Angular
PDF
Profiling ruby
KEY
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
performance vamos dormir mais?
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
Beyond PHP - It's not (just) about the code
Sinatra and JSONQuery Web Service
Beyond PHP - it's not (just) about the code
Rails Performance
Dynamic Tracing of your AMP web site
Top Node.js Metrics to Watch
Performance Optimization of Rails Applications
Beyond PHP - it's not (just) about the code
Практический опыт профайлинга и оптимизации производительности Ruby-приложений
Ruby on Rails Developer - Allerin
Distributed Load Testing with k6 - DevOps Barcelona
Distributed load testing with K6 - NDC London 2024
Hidden Gems of Ruby 1.9
fog or: How I Learned to Stop Worrying and Love the Cloud
Ruby on Rails Intro
Javascript Memory leaks and Performance & Angular
Profiling ruby
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Ad

More from Jano Suchal (20)

PDF
Slovensko.Digital: Čo ďalej?
PDF
Datanest 3.0
PDF
Improving code quality
PDF
Beyond search queries
PDF
Rank all the things!
PDF
Rank all the (geo) things!
PDF
Ako si vybrať programovácí jazyk alebo framework?
PPTX
Bonetics: Mastering Puppet Workshop
PPTX
Peter Mihalik: Puppet
PDF
Tomáš Čorej: Configuration management & CFEngine3
PDF
Ako si vybrať programovací jazyk a framework?
PDF
SQL: Query optimization in practice
PDF
Garelic: Google Analytics as App Performance monitoring
PDF
Miroslav Šimulčík: Temporálne databázy
PDF
Vojtech Rinik: Internship v USA - moje skúsenosti
PDF
Aký programovací jazyk a framework si vybrať a prečo?
PDF
Čo po GAMČI?
PDF
Petr Joachim: Redis na Super.cz
PDF
Metaprogramovanie #1
PDF
PostgreSQL: Advanced features in practice
Slovensko.Digital: Čo ďalej?
Datanest 3.0
Improving code quality
Beyond search queries
Rank all the things!
Rank all the (geo) things!
Ako si vybrať programovácí jazyk alebo framework?
Bonetics: Mastering Puppet Workshop
Peter Mihalik: Puppet
Tomáš Čorej: Configuration management & CFEngine3
Ako si vybrať programovací jazyk a framework?
SQL: Query optimization in practice
Garelic: Google Analytics as App Performance monitoring
Miroslav Šimulčík: Temporálne databázy
Vojtech Rinik: Internship v USA - moje skúsenosti
Aký programovací jazyk a framework si vybrať a prečo?
Čo po GAMČI?
Petr Joachim: Redis na Super.cz
Metaprogramovanie #1
PostgreSQL: Advanced features in practice

Recently uploaded (20)

PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
NewMind AI Monthly Chronicles - July 2025
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Big Data Technologies - Introduction.pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPT
Teaching material agriculture food technology
PPTX
Cloud computing and distributed systems.
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
The Rise and Fall of 3GPP – Time for a Sabbatical?
Mobile App Security Testing_ A Comprehensive Guide.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
The AUB Centre for AI in Media Proposal.docx
20250228 LYD VKU AI Blended-Learning.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
NewMind AI Monthly Chronicles - July 2025
Digital-Transformation-Roadmap-for-Companies.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Big Data Technologies - Introduction.pptx
Network Security Unit 5.pdf for BCA BBA.
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Teaching material agriculture food technology
Cloud computing and distributed systems.
How UI/UX Design Impacts User Retention in Mobile Apps.pdf

Profiling and monitoring ruby & rails applications

  • 1. Profiling and monitoring ruby/rails JÁN SUCHAL @JSUCHAL
  • 2. Optimalization  “If you can’t measure it, you can’t improve it.” – Lord Kelvin  Environment  development vs. production (hw, sw, load)  data (synthetic vs. real)  Bottlenecks  10sec * 1 run vs. 0.5s * 100 runs  run time * runs vs. development time  Microbenchmarks  waste of time vs. 20 * 1% = 20%  “There are three kinds of lies: lies, damned lies, and statistics.” – Benjamin Disraeli  single run vs. multiple runs  average vs. standard deviance, percentiles  cold vs. hot cache
  • 3. Profiler - Example # profiler/dates.rb require 'date' def create_days_after(date_str, n) after = Date.strptime(date_str) + n after.strftime("%Y-%m-%d") end 1000.times do create_days_after("1982-10-27", 5) end
  • 4. Ruby Profiler  $ gem install ruby-prof  $ ruby-prof dates.rb  How long does each method take?  $ ruby-prof dates.rb –m 3  Just methods above 3% time Thread ID: 7749480 Total: 0.653076 %self total self wait child calls name 12.97 0.19 0.08 0.00 0.18 2000 String#scan 11.57 0.08 0.08 0.00 0.00 205000 String#=== 6.87 0.18 0.04 0.00 0.14 1000 String#gsub 6.28 0.05 0.04 0.00 0.01 14000 Hash#values_at 4.08 0.03 0.03 0.00 0.00 80470 Hash#default 3.21 0.03 0.02 0.00 0.01 3000 Date#emit
  • 5. Ruby Profiler Thread ID: 7749480 Total: 0.653076 %self total self wait child calls name 12.97 0.19 0.08 0.00 0.18 2000 String#scan 11.57 0.08 0.08 0.00 0.00 205000 String#=== 6.87 0.18 0.04 0.00 0.14 1000 String#gsub 6.28 0.05 0.04 0.00 0.01 14000 Hash#values_at 4.08 0.03 0.03 0.00 0.00 80470 Hash#default 3.21 0.03 0.02 0.00 0.01 3000 Date#emit  total – time in method and children calls  self – time in method call  wait – wait time  child – time in child calls  call – number of times method invoked
  • 6. Ruby Profiler  $ ruby-prof dates.rb -m 3 -p graph  Which method calls what and how many times? Thread ID: 15523700 Total Time: 0.675587048 %total %self total self wait child calls Name 0.20 0.10 0.00 0.20 2000/2000 <Class::Date>#_strptime_i 30.28% 14.70% 0.20 0.10 0.00 0.20 2000 String#scan 0.04 0.04 0.00 0.00 110000/205000 String#=== 0.02 0.01 0.00 0.01 3000/5000 Date::Format::Bag#method_... 0.02 0.00 0.00 0.01 2000/3005 Class#new 0.01 0.01 0.00 0.00 5000/5000 String#sub! 0.01 0.00 0.00 0.01 2000/2000 Range#=== 0.00 0.00 0.00 0.00 3000/3000 String#to_i 0.00 0.00 0.00 0.00 2000/2000 <Class::Regexp>#quote 0.00 0.00 0.00 0.00 2000/2000 Regexp#=== 0.00 0.00 0.00 0.00 1000/1000 <Class::Date>#num_pattern? 0.00 0.00 0.00 0.00 1000/2000 <Class::Date>#_strptime_i
  • 7. Ruby Profiler Thread ID: 15523700 Total Time: 0.675587048 %total %self total self wait child calls Name 0.20 0.10 0.00 0.20 2000/2000 <Class::Date>#_strptime_i 30.28% 14.70% 0.20 0.10 0.00 0.20 2000 String#scan 0.04 0.04 0.00 0.00 110000/205000 String#=== 0.02 0.01 0.00 0.01 3000/5000 Date::Format::Bag#method_..  three parts  parent calls  method  children calls  calls – number of calls from method/total number of calls
  • 8. Ruby Profiler  $ ruby-prof dates.rb -p graph_html -m 3 > graph.html  $ ruby-prof dates.rb -p graph_html -m 3 –s self > graph.html
  • 9. Profiler - KCacheGrind  $ ruby-prof dates.rb -p call_tree -m 3 > dates1.grind  $ kcachegrind dates1.grind
  • 10. benchmark-ips require 'benchmark/ips' require 'ostruct' require 'hashr' require 'hashugar' SMALL_HASH = {:a => 1, :b => 2} Benchmark.ips do |x| x.report 'OpenStruct create small hash and access once', 'OpenStruct.new(SMALL_HASH).item5' x.report 'Hashr create small hash and access once', 'Hashr.new(SMALL_HASH).item5' x.report 'Hashugar create small hash and access once', 'Hashugar.new(SMALL_HASH).item5‘ end OpenStruct create small hash and access once 43858.0 (±5.5%) i/s - 221820 in 5.074250s (cycle=3697) Hashr create small hash and access once 67408.9 (±5.0%) i/s - 339780 in 5.053728s (cycle=5663) Hashugar create small hash and access once 230217.9 (±4.2%) i/s - 1152670 in 5.015705s (cycle=15790)
  • 11. Memory profiling  Patched ruby  $ rvm install 1.9.3 --patch railsexpress --name gc  $ ruby-prof --mode=allocations dates.rb –m 3 %self total self wait child calls name 59.23 6004.00 6004.00 0.00 0.00 1000 <Class::Date>#strptime 9.87 1000.00 1000.00 0.00 0.00 1000 Date#strftime 9.87 9004.00 1000.00 0.00 8004.00 1000 Object#create_days_after 9.87 1000.00 1000.00 0.00 0.00 1000 Date#+ 9.87 10004.00 1000.00 0.00 9004.00 1 Integer#times
  • 12. Rails / NewRelic Developer mode  gem 'newrelic_rpm‘  http://localhost:3000/newrelic  gem 'newrelic_rpm', git: 'git://github.com/jsuchal/rpm.git', branch: 'feature-profile-sorting'
  • 14. Rails / NewRelic Developer mode
  • 17. Custom Method Tracers # initializers/elastic_search_traces.rb require 'new_relic/agent/method_tracer‘ ElasticSearch.class_eval do include NewRelic::Agent::MethodTracer add_method_tracer :search, 'Custom/elasticsearch/search' add_method_tracer :index, 'Custom/elasticsearch/index' end
  • 18. NewRelic Production Monitoring  Web Transactions – controller actions drilldown  Transaction Traces – detailed slow requests  Slow SQL – slow queries  Background job monitoring  Availabality monitoring  Deployment tracking  Scalability analysis  ...  Server monitoring (load, disks, …)
  • 24. Most common performance problems  “1 + N query problem”  joins FTW!  Lack of proper indexing  Unnecessary ActiveRecord loading  e.g. count vs. size vs. length  Default GC parameters  37signals params  RUBY_HEAP_MIN_SLOTS=600000 # This is 60(!) times larger than default  RUBY_GC_MALLOC_LIMIT=59000000 # This is 7 times larger than default  RUBY_HEAP_FREE_MIN=100000 # This is 24 times larger than default  Unknown abstraction internals  e.g. OpenStruct