SlideShare une entreprise Scribd logo
1  sur  44
Télécharger pour lire hors ligne
Profiling Ruby
Where and what to optimize in your code
/
jobs@housetrip.com /
Nasir Jamal work@HouseTrip
@_nasj
profiling helps you to narrow down to
where optimization would be most useful
benchmarking allows you to easily isolate
optimizations and cross-compare them
Benchmarking
Realtime
puts Benchmark.realtime { 4000.times { |x| x**x } }
#=> 0.905972957611084
1. User CPU time
2. System CPU time
3. (1 + 2) i.e. User + System CPU time
4. Realtime
puts Benchmark.measure { 4000.times { |x| x**x } }
# => 0.890000 0.020000 0.910000 (0.909118)
Benchmark.bm do |bm|
bm.report { first_algorithm }
bm.report { second_algorithm}
…..
end
#=> user system total real
0.940000 0.010000 0.950000 ( 0.956572)
0.430000 0.010000 0.440000 ( 0.423467)
Benchmark.bm(14) do |bm|
bm.report(“first header”) { first_algorithm }
bm.report(“second header”) { second_algorithm}
…..
end
#=> user system total real
first header 0.940000 0.010000 0.950000 (0.956572)
second header 0.430000 0.010000 0.440000 (0.423467)
examples ...
Benchmark.bmbm(20) do |bm|
bm.report('append') do
str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4'
1_000_000.times { y = str1 << str2 << str3 << str4 }
end
bm.report('concat') do
str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4'
1_000_000.times { y = str1 + str2 + str3 + str4 }
end
bm.report('interpolate') do
str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4'
1_000_000.times { y = "#{str1}#{str2}#{str3}#{str4}" }
end
bm.report('interpolate one') do
str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4'
1_000_000.times { y = "string1string2string3#{str4}" }
end
end
.bmbm prevents result skewing
bmbm does rehearsal which includes any initialisation and GC run
then it does the real benchmark
#=> Rehearsal ---------------------------------------------
append 0.280000 0.000000 0.280000 ( 0.294505)
concat 0.470000 0.020000 0.490000 ( 0.481748)
interpolate 0.430000 0.010000 0.440000 ( 0.433404)
interpolate one 0.320000 0.000000 0.320000 ( 0.323479)
--------------------------------------- total: 1.530000sec
| Tests | user | system | total | real |
|:---------------|:--------:|:--------:|:---------:|-----------:|
|append | 0.260000 | 0.010000 | 0.270000 | (0.265732) |
|concat | 0.400000 | 0.010000 | 0.410000 | (0.396115) |
|interpolate | 0.400000 | 0.000000 | 0.400000 | (0.408096) |
|interpolate one | 0.280000 | 0.010000 | 0.290000 | (0.286443) |
Benchmark.bmbm(20) do |bm|
bm.report('gsub') do
1_0_000.times { Date.today.to_s.gsub!('-','') }
end
bm.report('strftime') do
1_0_000.times { Date.today.strftime("%Y%m%d") }
end
end
#=> Rehearsal -------------------------------------------
gsub 0.750000 0.000000 0.750000 ( 0.751547)
strftime 1.320000 0.000000 1.320000 ( 1.320621)
------------------------------------ total: 2.070000sec
| | user | system | total | real |
|:--------|:--------:|:---------:|:--------:|:-----------|
|gsub | 0.710000 | 0.000000 | 0.710000 | (0.709918) |
|strftime | 1.320000 | 0.000000 | 1.320000 | (1.315345) |
module Extendable
def name
@name
end
end
class Person
attr_accessor :name
end
require 'ostruct'
Benchmark.bmbm(20) do |bm|
bm.report('Class') do
1_00_000.times { p = Person.new; p.name='Joe'; p.name }
end
bm.report('Extends') do
1_00_000.times { p = Person1.new; p.extend Extendable; p.name='Joe'; p.name }
end
bm.report('Struct') do
1_00_000.times { person2 = Struct.new(:name); p = person2.new('Joe'); p.name }
end
bm.report('OpenStruct') do
1_00_000.times { p = OpenStruct.new(:name => 'Joe'); p.name }
end
end
#=> Rehearsal ---------------------------------------------
Class 0.080000 0.000000 0.080000 (0.086261)
Extends 0.410000 0.000000 0.410000 (0.407723)
Struct 1.490000 0.000000 1.490000 (1.490557)
OpenStruct 1.980000 0.010000 1.990000 (1.990507)
------------------------------------ total: 3.970000sec
| | user | system | total | real |
|:----------|:--------:|:--------:|:---------:|:-----------|
|Class | 0.080000 | 0.000000 | 0.080000 | (0.082448) |
|Extends | 0.400000 | 0.000000 | 0.400000 | (0.410884) |
|Struct | 1.480000 | 0.000000 | 1.480000 | (1.490531) |
|OpenStruct | 1.960000 | 0.010000 | 1.970000 | (1.965923) |
Profiling
perftools.rb
an adaptation of Google's perftools library to the Ruby land by Aman
Gupta
https://github.com/tmm1/perftools.rb
$gem install perftools.rb
does profiling via sampling method, where by default it takes
100 samples a second
examples ...
to see results
Interpreting the above columns:
1. Number of profiling samples in this function
2. Percentage of profiling samples in this function
3. Percentage of profiling samples in the functions printed so far
4. Number of profiling samples in this function and its callees
5. Percentage of profiling samples in this function and its callees
6. Function name
a = ''
PerfTools::CpuProfiler.start("/tmp/profiling/string_concat") do
100_000.times {|x| a += x.to_s}
end
$pprof.rb --text --ignore=Gem /tmp/profiling/string_concat
Total: 2939 samples
1497 50.9% 50.9% 1501 51.1% Object#irb_binding
1438 48.9% 99.9% 1438 48.9% garbage_collector
4 0.1% 100.0% 1500 51.0% Integer#times
to see results as graph
bigger the box, the more time spent there
1. Class Name
2. Method Name
3. local (percentage)
4. of cumulative (percentage)
brew install graphviz
$pprof.rb --gif --ignore=Gem /tmp/profiling/string_concat > /tmp/profiling/string_concat.gif
slightly hairy method
And on on ....
PerfTools::CpuProfiler.start("/tmp/profiling/property_search") do
100.times { PropertySearch.new.search }
end
$pprof.rb --text --ignore=Gem /tmp/profiling/property_search
Total: 6799 samples
2598 38.2% 38.2% 2598 38.2% garbage_collector
1761 25.9% 64.1% 3966 58.3% PropertySearch#set_price_filter_counts
390 5.7% 69.8% 1632 24.0% Object#detect
389 5.7% 75.6% 503 7.4% PropertySearch::PriceRange#contains?
358 5.3% 80.8% 358 5.3% Mysql2::Result#each
263 3.9% 84.7% 768 11.3% Object#select_values
199 2.9% 87.6% 236 3.5% ActiveRecord::ConnectionAdapters::Mysql2Adapter#execu
187 2.8% 90.4% 640 9.4% Property.collect_column
148 2.2% 92.6% 148 2.2% ActiveSupport::BufferedLogger#flush
114 1.7% 94.2% 114 1.7% Fixnum#<=
75 1.1% 95.3% 75 1.1% Array#join
67 1.0% 96.3% 76 1.1% Array#map
47 0.7% 97.0% 47 0.7% ActiveRecord::ConnectionAdapters::Column#type_cast
44 0.6% 97.7% 295 4.3% Array#collect
32 0.5% 98.1% 388 5.7% Object#to_a
28 0.4% 98.5% 28 0.4% PropertySearch#day_count
15 0.2% 98.8% 140 2.1% ActiveRecord::ConnectionAdapters::Mysql2Adapter#selec
9 0.1% 98.9% 4199 61.8% PropertySearch#search
$pprof.rb --help
Qcachegrind
How to setup?
http://langui.sh/2011/06/16/how-to-install-qcachegrind-
kcachegrind-on-mac-osx-snow-leopard/
$pprof.rb --callgrind /tmp/profiling/property_search > /tmp/profiling/property_search.callgr
graph
To use with Rails
Valid default_printer values are pdf, text, raw, gif, callgrind
# Gemfile
gem 'rack-perftools_profiler', :require => false
# config/environment.rb
config.middleware.use ::Rack::PerftoolsProfiler,
:default_printer => 'gif',
:bundler => true,
:mode => :cputime,
:frequency => 250
profile=true will enable profiling
times=10 will hit the page for 10 times
will store the results in profile_ppp_page.txt
RACK_PROFILER=true script/server
curl -o profile_ppp_page.txt 
"http://localhost:3000/en/rentals/107605?profile=true&times=10"
ruby-prof
OR
$gem install ruby-prof
#Gemfile
gem 'ruby-prof', :require => false
types of measures
RubyProf.measure_mode = RubyProf::PROCESS_TIME
RubyProf.measure_mode = RubyProf::WALL_TIME
RubyProf.measure_mode = RubyProf::CPU_TIME
RubyProf.measure_mode = RubyProf::ALLOCATIONS
RubyProf.measure_mode = RubyProf::MEMORY
RubyProf.measure_mode = RubyProf::GC_RUNS
RubyProf.measure_mode = RubyProf::GC_TIME
types of printers
RubyProf::FlatPrinter
RubyProf::FlatPrinterWithLineNumbers
RubyProf::GraphPrinter
RubyProf::GraphHtmlPrinter
RubyProf::CallTreePrinter
RubyProf::CallStackPrinter
RubyProf::MultiPrinter
examples ...
GraphHtmlPrinter
result = RubyProf.profile { PropertySearch.new.search }
printer = RubyProf::GraphHtmlPrinter.new(result)
File.open("tmp/profile_data.html", 'w') { |file| printer.print(file)}
profile_data.html
CallStackPrinter
result = RubyProf.profile { PropertySearch.new.search }
printer = RubyProf::CallStackPrinter.new(result)
File.open("tmp/profile_data.html", 'w') { |file| printer.print(file)}
profile_data.html
CallTreePrinter
result = RubyProf.profile { PropertySearch.new.search }
printer = RubyProf::CallTreePrinter.new(result)
File.open("tmp/profile_data", 'w') { |file| printer.print(file)}
profile_data (qcachegrind)
In Rails
2.x.x
3.x.x
Or just use rake tasks
script/performance/benchmarker 10 'Class.method_name' 'AnotherClass.method_name'
script/performance/profiler 'Class.method_name' 10 graph
script/performance/profiler 'Class.method_name' 10 graph_html 2> property.html && open prope
rails benchmarker 'Class.method_name'
rails profiler 'Class.method_name' --runs 3 --metrics cpu_time,memory
rake test:benchmark
rake test:profile
rake test:profile TEST=test/performance/home_page_test.rb
But from Rails 4.0
performance tests are no longer part of the default
stack
https://github.com/rails/rails-perftest
Questions?
jobs@housetrip.com
We are hiring
Thank you

Contenu connexe

Tendances

Tendances (20)

Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
An eternal question of timing
An eternal question of timingAn eternal question of timing
An eternal question of timing
 
On the Expressiveness of Attribute-based Communication
On the Expressiveness of Attribute-based CommunicationOn the Expressiveness of Attribute-based Communication
On the Expressiveness of Attribute-based Communication
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
 
Use C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in GeckoUse C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in Gecko
 
Keras cheat sheet_python
Keras cheat sheet_pythonKeras cheat sheet_python
Keras cheat sheet_python
 
Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36
 
The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184The Ring programming language version 1.5.3 book - Part 88 of 184
The Ring programming language version 1.5.3 book - Part 88 of 184
 
The Ring programming language version 1.9 book - Part 91 of 210
The Ring programming language version 1.9 book - Part 91 of 210The Ring programming language version 1.9 book - Part 91 of 210
The Ring programming language version 1.9 book - Part 91 of 210
 
The Ring programming language version 1.4 book - Part 21 of 30
The Ring programming language version 1.4 book - Part 21 of 30The Ring programming language version 1.4 book - Part 21 of 30
The Ring programming language version 1.4 book - Part 21 of 30
 
Testing in those hard to reach places
Testing in those hard to reach placesTesting in those hard to reach places
Testing in those hard to reach places
 
The Ring programming language version 1.6 book - Part 82 of 189
The Ring programming language version 1.6 book - Part 82 of 189The Ring programming language version 1.6 book - Part 82 of 189
The Ring programming language version 1.6 book - Part 82 of 189
 
Managing Mocks
Managing MocksManaging Mocks
Managing Mocks
 
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
 
Python faster for loop
Python faster for loopPython faster for loop
Python faster for loop
 
Concurrency Concepts in Java
Concurrency Concepts in JavaConcurrency Concepts in Java
Concurrency Concepts in Java
 
Tools for Solving Performance Issues
Tools for Solving Performance IssuesTools for Solving Performance Issues
Tools for Solving Performance Issues
 
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
 
How to build a debug view almost for free
How to build a debug view almost for freeHow to build a debug view almost for free
How to build a debug view almost for free
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 

En vedette

Arqu hardware 11 - fuentes de poder (63170)
Arqu hardware   11 - fuentes de poder (63170)Arqu hardware   11 - fuentes de poder (63170)
Arqu hardware 11 - fuentes de poder (63170)
dianatique
 
Arqu hardware 03 - microprocesadores intel (63170)
Arqu hardware   03 - microprocesadores intel (63170)Arqu hardware   03 - microprocesadores intel (63170)
Arqu hardware 03 - microprocesadores intel (63170)
dianatique
 
Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...
Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...
Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...
jeanhuge
 
Arqu hardware 02 - sockets (63170)
Arqu hardware   02 - sockets (63170)Arqu hardware   02 - sockets (63170)
Arqu hardware 02 - sockets (63170)
dianatique
 
Sustainability Assessment in Benin
Sustainability Assessment in BeninSustainability Assessment in Benin
Sustainability Assessment in Benin
jeanhuge
 
Arqu hardware 03 - microprocesadores intel (63170)
Arqu hardware   03 - microprocesadores intel (63170)Arqu hardware   03 - microprocesadores intel (63170)
Arqu hardware 03 - microprocesadores intel (63170)
dianatique
 
Arqu hardware 02 - sockets (63170)
Arqu hardware   02 - sockets (63170)Arqu hardware   02 - sockets (63170)
Arqu hardware 02 - sockets (63170)
dianatique
 
Arqu hardware 02 - sockets (63170)
Arqu hardware   02 - sockets (63170)Arqu hardware   02 - sockets (63170)
Arqu hardware 02 - sockets (63170)
dianatique
 
Arqu hardware 11 - fuentes de poder (63170)
Arqu hardware   11 - fuentes de poder (63170)Arqu hardware   11 - fuentes de poder (63170)
Arqu hardware 11 - fuentes de poder (63170)
dianatique
 

En vedette (19)

internship report (1)
internship report (1)internship report (1)
internship report (1)
 
Arqu hardware 11 - fuentes de poder (63170)
Arqu hardware   11 - fuentes de poder (63170)Arqu hardware   11 - fuentes de poder (63170)
Arqu hardware 11 - fuentes de poder (63170)
 
Arqu hardware 03 - microprocesadores intel (63170)
Arqu hardware   03 - microprocesadores intel (63170)Arqu hardware   03 - microprocesadores intel (63170)
Arqu hardware 03 - microprocesadores intel (63170)
 
Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...
Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...
Presentation at the SKB Stockholm Spring Talks 2011 \'Societal Approaches to ...
 
Love your pull_requests
Love your pull_requestsLove your pull_requests
Love your pull_requests
 
仮想環境で仕事をしよう
仮想環境で仕事をしよう仮想環境で仕事をしよう
仮想環境で仕事をしよう
 
Sustainability Assessment of Poverty Reduction Strategy Papers
Sustainability Assessment of Poverty Reduction Strategy PapersSustainability Assessment of Poverty Reduction Strategy Papers
Sustainability Assessment of Poverty Reduction Strategy Papers
 
Arqu hardware 02 - sockets (63170)
Arqu hardware   02 - sockets (63170)Arqu hardware   02 - sockets (63170)
Arqu hardware 02 - sockets (63170)
 
Sustainability Assessment in Benin
Sustainability Assessment in BeninSustainability Assessment in Benin
Sustainability Assessment in Benin
 
DEPRESSURIZATION OF URBAN MEGA PUBLIC HOSPITAL.pptx Mid term ppt
DEPRESSURIZATION OF URBAN MEGA PUBLIC HOSPITAL.pptx Mid term pptDEPRESSURIZATION OF URBAN MEGA PUBLIC HOSPITAL.pptx Mid term ppt
DEPRESSURIZATION OF URBAN MEGA PUBLIC HOSPITAL.pptx Mid term ppt
 
もう一度始めるUstream入門
もう一度始めるUstream入門もう一度始めるUstream入門
もう一度始めるUstream入門
 
Arqu hardware 03 - microprocesadores intel (63170)
Arqu hardware   03 - microprocesadores intel (63170)Arqu hardware   03 - microprocesadores intel (63170)
Arqu hardware 03 - microprocesadores intel (63170)
 
Arqu hardware 02 - sockets (63170)
Arqu hardware   02 - sockets (63170)Arqu hardware   02 - sockets (63170)
Arqu hardware 02 - sockets (63170)
 
Arqu hardware 02 - sockets (63170)
Arqu hardware   02 - sockets (63170)Arqu hardware   02 - sockets (63170)
Arqu hardware 02 - sockets (63170)
 
Arqu hardware 11 - fuentes de poder (63170)
Arqu hardware   11 - fuentes de poder (63170)Arqu hardware   11 - fuentes de poder (63170)
Arqu hardware 11 - fuentes de poder (63170)
 
A celebration of breakfast
A celebration of breakfast A celebration of breakfast
A celebration of breakfast
 
Ppt
PptPpt
Ppt
 
Al hijamah
Al hijamahAl hijamah
Al hijamah
 
Osmotic fragility &amp; rbc membrane defects 050916
Osmotic fragility &amp; rbc membrane defects 050916Osmotic fragility &amp; rbc membrane defects 050916
Osmotic fragility &amp; rbc membrane defects 050916
 

Similaire à Profiling ruby

Similaire à Profiling ruby (20)

Where the wild things are - Benchmarking and Micro-Optimisations
Where the wild things are - Benchmarking and Micro-OptimisationsWhere the wild things are - Benchmarking and Micro-Optimisations
Where the wild things are - Benchmarking and Micro-Optimisations
 
Performance and how to measure it - ProgSCon London 2016
Performance and how to measure it - ProgSCon London 2016Performance and how to measure it - ProgSCon London 2016
Performance and how to measure it - ProgSCon London 2016
 
Enhancing the performance of kmeans algorithm
Enhancing the performance of kmeans algorithmEnhancing the performance of kmeans algorithm
Enhancing the performance of kmeans algorithm
 
Benchy: Lightweight framework for Performance Benchmarks
Benchy: Lightweight framework for Performance Benchmarks Benchy: Lightweight framework for Performance Benchmarks
Benchy: Lightweight framework for Performance Benchmarks
 
(PFC302) Performance Benchmarking on AWS | AWS re:Invent 2014
(PFC302) Performance Benchmarking on AWS | AWS re:Invent 2014(PFC302) Performance Benchmarking on AWS | AWS re:Invent 2014
(PFC302) Performance Benchmarking on AWS | AWS re:Invent 2014
 
Code instrumentation
Code instrumentationCode instrumentation
Code instrumentation
 
Machine Learning Model for M.S admissions
Machine Learning Model for M.S admissionsMachine Learning Model for M.S admissions
Machine Learning Model for M.S admissions
 
Machinelearning Spark Hadoop User Group Munich Meetup 2016
Machinelearning Spark Hadoop User Group Munich Meetup 2016Machinelearning Spark Hadoop User Group Munich Meetup 2016
Machinelearning Spark Hadoop User Group Munich Meetup 2016
 
Capacity Planning for Linux Systems
Capacity Planning for Linux SystemsCapacity Planning for Linux Systems
Capacity Planning for Linux Systems
 
Mysql handle socket
Mysql handle socketMysql handle socket
Mysql handle socket
 
PostgreSQL query planner's internals
PostgreSQL query planner's internalsPostgreSQL query planner's internals
PostgreSQL query planner's internals
 
Linux Systems Performance 2016
Linux Systems Performance 2016Linux Systems Performance 2016
Linux Systems Performance 2016
 
maxbox starter60 machine learning
maxbox starter60 machine learningmaxbox starter60 machine learning
maxbox starter60 machine learning
 
Best Practices for Benchmarking and Performance Analysis in the Cloud (ENT305...
Best Practices for Benchmarking and Performance Analysis in the Cloud (ENT305...Best Practices for Benchmarking and Performance Analysis in the Cloud (ENT305...
Best Practices for Benchmarking and Performance Analysis in the Cloud (ENT305...
 
Recent my sql_performance Test detail
Recent my sql_performance Test detailRecent my sql_performance Test detail
Recent my sql_performance Test detail
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
Using PostgreSQL statistics to optimize performance
Using PostgreSQL statistics to optimize performance Using PostgreSQL statistics to optimize performance
Using PostgreSQL statistics to optimize performance
 
Benchmarking and PHPBench
Benchmarking and PHPBenchBenchmarking and PHPBench
Benchmarking and PHPBench
 
Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨
 
Performance is a feature! - London .NET User Group
Performance is a feature! - London .NET User GroupPerformance is a feature! - London .NET User Group
Performance is a feature! - London .NET User Group
 

Dernier

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 

Profiling ruby

  • 1. Profiling Ruby Where and what to optimize in your code / jobs@housetrip.com / Nasir Jamal work@HouseTrip @_nasj
  • 2. profiling helps you to narrow down to where optimization would be most useful
  • 3. benchmarking allows you to easily isolate optimizations and cross-compare them
  • 5. Realtime puts Benchmark.realtime { 4000.times { |x| x**x } } #=> 0.905972957611084
  • 6. 1. User CPU time 2. System CPU time 3. (1 + 2) i.e. User + System CPU time 4. Realtime puts Benchmark.measure { 4000.times { |x| x**x } } # => 0.890000 0.020000 0.910000 (0.909118)
  • 7. Benchmark.bm do |bm| bm.report { first_algorithm } bm.report { second_algorithm} ….. end #=> user system total real 0.940000 0.010000 0.950000 ( 0.956572) 0.430000 0.010000 0.440000 ( 0.423467)
  • 8. Benchmark.bm(14) do |bm| bm.report(“first header”) { first_algorithm } bm.report(“second header”) { second_algorithm} ….. end #=> user system total real first header 0.940000 0.010000 0.950000 (0.956572) second header 0.430000 0.010000 0.440000 (0.423467)
  • 10. Benchmark.bmbm(20) do |bm| bm.report('append') do str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4' 1_000_000.times { y = str1 << str2 << str3 << str4 } end bm.report('concat') do str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4' 1_000_000.times { y = str1 + str2 + str3 + str4 } end bm.report('interpolate') do str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4' 1_000_000.times { y = "#{str1}#{str2}#{str3}#{str4}" } end bm.report('interpolate one') do str1, str2, str3, str4 = 'string1', 'string2', 'string3', 'string4' 1_000_000.times { y = "string1string2string3#{str4}" } end end .bmbm prevents result skewing
  • 11. bmbm does rehearsal which includes any initialisation and GC run then it does the real benchmark #=> Rehearsal --------------------------------------------- append 0.280000 0.000000 0.280000 ( 0.294505) concat 0.470000 0.020000 0.490000 ( 0.481748) interpolate 0.430000 0.010000 0.440000 ( 0.433404) interpolate one 0.320000 0.000000 0.320000 ( 0.323479) --------------------------------------- total: 1.530000sec | Tests | user | system | total | real | |:---------------|:--------:|:--------:|:---------:|-----------:| |append | 0.260000 | 0.010000 | 0.270000 | (0.265732) | |concat | 0.400000 | 0.010000 | 0.410000 | (0.396115) | |interpolate | 0.400000 | 0.000000 | 0.400000 | (0.408096) | |interpolate one | 0.280000 | 0.010000 | 0.290000 | (0.286443) |
  • 12. Benchmark.bmbm(20) do |bm| bm.report('gsub') do 1_0_000.times { Date.today.to_s.gsub!('-','') } end bm.report('strftime') do 1_0_000.times { Date.today.strftime("%Y%m%d") } end end #=> Rehearsal ------------------------------------------- gsub 0.750000 0.000000 0.750000 ( 0.751547) strftime 1.320000 0.000000 1.320000 ( 1.320621) ------------------------------------ total: 2.070000sec | | user | system | total | real | |:--------|:--------:|:---------:|:--------:|:-----------| |gsub | 0.710000 | 0.000000 | 0.710000 | (0.709918) | |strftime | 1.320000 | 0.000000 | 1.320000 | (1.315345) |
  • 13. module Extendable def name @name end end class Person attr_accessor :name end require 'ostruct' Benchmark.bmbm(20) do |bm| bm.report('Class') do 1_00_000.times { p = Person.new; p.name='Joe'; p.name } end bm.report('Extends') do 1_00_000.times { p = Person1.new; p.extend Extendable; p.name='Joe'; p.name } end bm.report('Struct') do 1_00_000.times { person2 = Struct.new(:name); p = person2.new('Joe'); p.name } end bm.report('OpenStruct') do 1_00_000.times { p = OpenStruct.new(:name => 'Joe'); p.name } end end
  • 14. #=> Rehearsal --------------------------------------------- Class 0.080000 0.000000 0.080000 (0.086261) Extends 0.410000 0.000000 0.410000 (0.407723) Struct 1.490000 0.000000 1.490000 (1.490557) OpenStruct 1.980000 0.010000 1.990000 (1.990507) ------------------------------------ total: 3.970000sec | | user | system | total | real | |:----------|:--------:|:--------:|:---------:|:-----------| |Class | 0.080000 | 0.000000 | 0.080000 | (0.082448) | |Extends | 0.400000 | 0.000000 | 0.400000 | (0.410884) | |Struct | 1.480000 | 0.000000 | 1.480000 | (1.490531) | |OpenStruct | 1.960000 | 0.010000 | 1.970000 | (1.965923) |
  • 16. perftools.rb an adaptation of Google's perftools library to the Ruby land by Aman Gupta https://github.com/tmm1/perftools.rb $gem install perftools.rb
  • 17. does profiling via sampling method, where by default it takes 100 samples a second
  • 19. to see results Interpreting the above columns: 1. Number of profiling samples in this function 2. Percentage of profiling samples in this function 3. Percentage of profiling samples in the functions printed so far 4. Number of profiling samples in this function and its callees 5. Percentage of profiling samples in this function and its callees 6. Function name a = '' PerfTools::CpuProfiler.start("/tmp/profiling/string_concat") do 100_000.times {|x| a += x.to_s} end $pprof.rb --text --ignore=Gem /tmp/profiling/string_concat Total: 2939 samples 1497 50.9% 50.9% 1501 51.1% Object#irb_binding 1438 48.9% 99.9% 1438 48.9% garbage_collector 4 0.1% 100.0% 1500 51.0% Integer#times
  • 20. to see results as graph bigger the box, the more time spent there 1. Class Name 2. Method Name 3. local (percentage) 4. of cumulative (percentage) brew install graphviz $pprof.rb --gif --ignore=Gem /tmp/profiling/string_concat > /tmp/profiling/string_concat.gif
  • 21. slightly hairy method And on on .... PerfTools::CpuProfiler.start("/tmp/profiling/property_search") do 100.times { PropertySearch.new.search } end $pprof.rb --text --ignore=Gem /tmp/profiling/property_search Total: 6799 samples 2598 38.2% 38.2% 2598 38.2% garbage_collector 1761 25.9% 64.1% 3966 58.3% PropertySearch#set_price_filter_counts 390 5.7% 69.8% 1632 24.0% Object#detect 389 5.7% 75.6% 503 7.4% PropertySearch::PriceRange#contains? 358 5.3% 80.8% 358 5.3% Mysql2::Result#each 263 3.9% 84.7% 768 11.3% Object#select_values 199 2.9% 87.6% 236 3.5% ActiveRecord::ConnectionAdapters::Mysql2Adapter#execu 187 2.8% 90.4% 640 9.4% Property.collect_column 148 2.2% 92.6% 148 2.2% ActiveSupport::BufferedLogger#flush 114 1.7% 94.2% 114 1.7% Fixnum#<= 75 1.1% 95.3% 75 1.1% Array#join 67 1.0% 96.3% 76 1.1% Array#map 47 0.7% 97.0% 47 0.7% ActiveRecord::ConnectionAdapters::Column#type_cast 44 0.6% 97.7% 295 4.3% Array#collect 32 0.5% 98.1% 388 5.7% Object#to_a 28 0.4% 98.5% 28 0.4% PropertySearch#day_count 15 0.2% 98.8% 140 2.1% ActiveRecord::ConnectionAdapters::Mysql2Adapter#selec 9 0.1% 98.9% 4199 61.8% PropertySearch#search
  • 22.
  • 25. $pprof.rb --callgrind /tmp/profiling/property_search > /tmp/profiling/property_search.callgr
  • 26. graph
  • 27. To use with Rails Valid default_printer values are pdf, text, raw, gif, callgrind # Gemfile gem 'rack-perftools_profiler', :require => false # config/environment.rb config.middleware.use ::Rack::PerftoolsProfiler, :default_printer => 'gif', :bundler => true, :mode => :cputime, :frequency => 250
  • 28. profile=true will enable profiling times=10 will hit the page for 10 times will store the results in profile_ppp_page.txt RACK_PROFILER=true script/server curl -o profile_ppp_page.txt "http://localhost:3000/en/rentals/107605?profile=true&times=10"
  • 29.
  • 30. ruby-prof OR $gem install ruby-prof #Gemfile gem 'ruby-prof', :require => false
  • 31. types of measures RubyProf.measure_mode = RubyProf::PROCESS_TIME RubyProf.measure_mode = RubyProf::WALL_TIME RubyProf.measure_mode = RubyProf::CPU_TIME RubyProf.measure_mode = RubyProf::ALLOCATIONS RubyProf.measure_mode = RubyProf::MEMORY RubyProf.measure_mode = RubyProf::GC_RUNS RubyProf.measure_mode = RubyProf::GC_TIME
  • 34. GraphHtmlPrinter result = RubyProf.profile { PropertySearch.new.search } printer = RubyProf::GraphHtmlPrinter.new(result) File.open("tmp/profile_data.html", 'w') { |file| printer.print(file)}
  • 36. CallStackPrinter result = RubyProf.profile { PropertySearch.new.search } printer = RubyProf::CallStackPrinter.new(result) File.open("tmp/profile_data.html", 'w') { |file| printer.print(file)}
  • 38. CallTreePrinter result = RubyProf.profile { PropertySearch.new.search } printer = RubyProf::CallTreePrinter.new(result) File.open("tmp/profile_data", 'w') { |file| printer.print(file)}
  • 40. In Rails 2.x.x 3.x.x Or just use rake tasks script/performance/benchmarker 10 'Class.method_name' 'AnotherClass.method_name' script/performance/profiler 'Class.method_name' 10 graph script/performance/profiler 'Class.method_name' 10 graph_html 2> property.html && open prope rails benchmarker 'Class.method_name' rails profiler 'Class.method_name' --runs 3 --metrics cpu_time,memory rake test:benchmark rake test:profile rake test:profile TEST=test/performance/home_page_test.rb
  • 41. But from Rails 4.0 performance tests are no longer part of the default stack https://github.com/rails/rails-perftest