This one liner you can add to your Pry to see how long a single method call takes.
def pmeasure(&block)
now = Time.now.to_f
yield
duration = Time.now.to_f - now
puts "Finished in #{duration.round(6)}s"
end
# pmeasure { sleep 1 }
You can use the benchmark
library in native Ruby for simple tests.
require 'benchmark'
puts Benchmark.measure {
evens = []
arrays = [[1,2,3], [4,2,1], [3,4,2], [1,2,1]]
arrays.each do |array|
array.each do |num|
evens << num if num.even?
end
end
}
evens = []
arrays = [[1,2,3], [4,2,1], [3,4,2], [1,2,1]]
arrays.each do |array|
array.each do |num|
evens << num if num.even?
end
end
arrays.inject([]) do |result, arr|
result + arr.select { |x| x.even? }
end
arrays = [[1,2,3], [4,2,1], [3,4,2], [1,2,1]]
n = 100_000
Benchmark.bmbm do |x|
x.report("inject") do
n.times do
array.inject(0, :+)
end
end
x.report("sum") do
n.times do
array.sum
end
end
end
Use benchmark-ips to figure out how many times to run the given function to get interesting data.
require 'benchmark/ips'
Benchmark.ips do |x|
# Configure the number of seconds used during
# the warmup phase (default 2) and calculation phase (default 5)
x.config(:time => 5, :warmup => 2)
# These parameters can also be configured this way
x.time = 5
x.warmup = 2
# Typical mode, runs the block as many times as it can
x.report("addition") { 1 + 2 }
# To reduce overhead, the number of iterations is passed in
# and the block must run the code the specific number of times.
# Used for when the workload is very small and any overhead
# introduces incorrectable errors.
x.report("addition2") do |times|
i = 0
while i < times
1 + 2
i += 1
end
end
# To reduce overhead even more, grafts the code given into
# the loop that performs the iterations internally to reduce
# overhead. Typically not needed, use the |times| form instead.
x.report("addition3", "1 + 2")
# Really long labels should be formatted correctly
x.report("addition-test-long-label") { 1 + 2 }
# Compare the iterations per second of the various reports!
x.compare!
end
Sometimes you want to find out why your logic is slow. You can use rack-mini-profiler for Ruby on Rails apps.
You can add these tags to the end of your URL to instrument any Rails action.
?pp=flamegraph
?pp=flamegraph
StackProf works well for Ruby code.
StackProf.run(mode: :cpu, out: 'tmp/stackprof-cpu-myapp.dump', raw: true) do
# my expensive logic
end
# Open tmp/stackprof-cpu-myapp.dump to see the results.
For identifying the source of long running queries, I like sqlcommenter.
gem "activerecord-sql_commenter", require: "active_record/sql_commenter"
# application.rb
config.active_record.query_log_tags_enabled = true
config.active_record.query_log_tags = [ :application, :controller, :action, :job ]
config.active_record.cache_query_log_tags = true