Ruby on Rails: Performance
November 25, 2023Profiling
gem install stackprof
StackProf.run(mode: :cpu, raw: true, out: 'tmp/stackprof-cpu-myapp.dump') do
#...
end
# mode: cpu, wall, object. use object for memory
gem install stackprof-webnav
stackprof-webnav -f /path/to/stackprof.dump
Active Record
Maximum Number / Calculate Needs
A released connection will be returned to the pool, but not disconnect from the database server. The connection will remain connected in the pool, waiting for a new thread to request a connection. Hence the connection will count against your database server's maximum number of connections.
Only when a connection in the pool remains unused for more than 5 minutes, ActiveRecord will actually close the connection. You can configure this by setting the idle_timeout in your database.yml.
-- Using ActiveRecord with threads might use more database connections than you think
(2 pods * 3 workers) * (1 pod * 10 sidekiq workers) = 6 * 10 = 60 connections
((2 pods * 3 workers) * (1 pod * 10 sidekiq workers)) * 5 threads = (6 * 10) * 5 = 300 connections
reaping_frequency
: when to look for connections from inactive threads
ActiveRecord::Base.clear_active_connections!
: clears all active connections and diconnects forcibly
ActiveRecord::Base.connection_pool.release_connection
: releases the connection back to the pool without disconnecting so it can be reused
Reducing memory
- reduce sidekiq threads
- use
MALLOC_ARENA_MAX=2
as an env var
Caching
rails dev:cache # will enable/disable the cache if you have the default config in rails 5+
Example cache config in development.rb
if Rails.root.join('tmp/caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.static_cache_control = "public, max-age=172800"
config.cache_store = :mem_cache_store
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end