Track problem
Use some kind of monitoring solution to track server perfomance. You can choose from something more general, like Nagios, NewRlic or Stackdriver, to something specifilly tailored for Rails like Skylight or Scout.
Narrow down source of a problem
N+1 problem
Easy to fix when you know you have one. Use Skylight or Bullet to detect it. You also can discover it from rack-mini-profiler or RailsPanel.
Slow queries
Use the index, Luke. Use Skylight or DBs slow queries log to detect a problem.
Generally slow
Use profiler to detect why is your application is slow. Use stackprof in :wall
mode or rack-mini-profiler with ?pp=flamegraph
.
stackprof
require 'stackprof'
require File.expand_path('../../config/environment', __FILE__)
exit unless Rails.env.development?
sp = (ENV['STACKPROF'] || :wall).to_sym
StackProf.start(mode: sp, raw: true)
# code which we want to test
StackProf.stop
StackProf.results(File.join(Dir.pwd, "tmp/stackprof-#{sp}.dump"))
stackprof tmp/stackprof-wall.dump --text
rack-mini-profiler
# For memory profiling (requires Ruby MRI 2.1+)
gem 'memory_profiler'
# For call-stack profiling flamegraphs (requires Ruby MRI 2.0.0+)
gem 'flamegraph'
gem 'stackprof' # For Ruby MRI 2.1+
gem 'rack-mini-profiler', require: false
config/initializers/rack_profiler.rb
if Rails.env == 'development'
require 'rack-mini-profiler'
# initialization is skipped so trigger it
Rack::MiniProfilerRails.initialize!(Rails.application)
# set RedisStore
uri = URI.parse(ENV.fetch("REDIS_URI"))
Rack::MiniProfiler.config.storage_options = { :host => uri.host, :port => uri.port, :password => uri.password }
Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore
end
Consumes a lot of memory
Use profiler to detect why is your application is slow. Use stackprof in :object
moder or rack-mini-profiler with ?pp=analyze-memory
or memory_profiler.
Also check Derailed Benchmarks: bundle exec derailed bundle:mem
.
Also gc_tracer, allocation_tracer, allocation_stats and built-in ObjectSpace
can help.
config.ru
require ::File.expand_path('../config/environment', __FILE__)
require 'rack/gc_tracer'
require 'rack/allocation_tracer'
use Rack::GCTracerMiddleware, view_page_path: '/gc_tracer', filename: '/tmp/rails-gc_tracer'
use Rack::AllocationTracerMiddleware
run Rails.application
Check how GC works
Use rack-mini-profiler with ?pp=profile-gc
, gc_tracer or built-in GC::Profiler
.
To read:
- That’s Not a Memory Leak, It’s Bloat, 2009
- Demystifying the Ruby GC, 2013
- Ruby 2.1: RGenGC, 2013
- Watching and Understanding the Ruby 2.1 Garbage Collector at Work, 2014
- Ruby GC Tuning Parameters, 2014
- Incremental Garbage Collection in Ruby 2.2, 2015
- Methods of Memory Management in MRI, 2016
- Understanding Ruby GC through GC.stat, 2017
- Object ID in MRI, 2017
Hunting memory errors outside of Ruby object space
Use ruby with jemalloc and jemal. Use this command to check if ruby compiled with jemalloc: ruby -r rbconfig -e "puts RbConfig::CONFIG['LIBS']"
.
To read:
if ENV['JEMALLOC_STATS']
STDERR.puts "JEMALLOC_STATS enabled"
require 'jemal'
if Jemal.jemalloc_builtin?
STDERR.puts "jemalloc found"
Thread.new do
first = true
while true
sleep 5
stats = Jemal.stats
stats[:ts] = Time.now.utc.to_i
File.open(Rails.root + 'log/jemalloc.log', first ? 'w' : 'a') do |f|
f.puts stats.to_json
end
first = false
end
end
end
end
Other tools
- https://github.com/basecamp/trashed
- http://rbkit.codemancers.com/
- https://github.com/dpogue/rails_server_timings
- https://github.com/airbnb/hammerspace
About memory
- https://brandur.org/ruby-memory
- https://github.com/benoittgt/understand_ruby_memory
- http://eng.rightscale.com/2015/09/16/how-to-debug-ruby-memory-issues.html
- https://docs.newrelic.com/docs/agents/ruby-agent/features/garbage-collection#gc_setup
Benchmark
Use built-in ruby module Benchmark
and benchmark-memory.
require "benchmark"
Benchmark.benchmark(Benchmark::CAPTION, 7, Benchmark::FORMAT) do |x|
x.report("test:"){ ypur_code }
end
Faster gems
Faster than default implementations:
gem "escape_utils"
gem "fast_blank"
gem "oj"
gem "faster_path"
gem "ox"
gem "hamlit"
gem "mini_mime"
gem "fast_gettext"
Faster boot
Super fast ruby
Projects That Are Making Blazing Fast Ruby a Reality, 2016. Polyglot From The Very Old To The Very New.