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
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)
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