[Awesome Ruby Gem] Use rack-mini-profiler gem to displays speed badge for every html page

rack-mini-profiler

rack-mini-profiler gem is a middleware that displays speed badge for every html page. Designed to work both in production and in development.

Features

  • Database profiling - Currently supports Mysql2, Postgres, Oracle (oracle_enhanced ~> 1.5.0) and Mongoid3 (with fallback support to ActiveRecord)

  • Call-stack profiling - Flame graphs showing time spent by gem

  • Memory profiling - Per-request memory usage, GC stats, and global allocation metrics

Installation

You can install it as a gem:

1
$ gem install rack-mini-profiler

or add it into a Gemfile (Bundler):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Gemfile

# Put gems used only for development or testing in the appropriate group in the Gemfile
group :development do
# GitHub - MiniProfiler/rack-mini-profiler: Profiler for your development and production Ruby rack apps.
# https://github.com/MiniProfiler/rack-mini-profiler
# NOTE: Be sure to require rack_mini_profiler below the pg and mysql gems in your Gemfile. rack_mini_profiler will identify these gems if they are loaded to insert instrumentation. If included too early no SQL will show up.
gem 'rack-mini-profiler', '2.3.1'

# You can also include optional libraries to enable additional features.
# For memory profiling
gem 'memory_profiler'

# For call-stack profiling flamegraphs
gem 'stackprof'
end

Then, run bundle install.

1
$ bundle install

Usage

Rails

All you have to do is to include the Gem and you’re good to go in development. See notes below for use in production.

Rails and manual initialization

In case you need to make sure rack_mini_profiler is initialized after all other gems, or you want to execute some code before rack_mini_profiler required:

1
gem 'rack-mini-profiler', require: false

Note the require: false part - if omitted, it will cause the Railtie for the mini-profiler to be loaded outright, and an attempt to re-initialize it manually will raise an exception.


Then run the generator which will set up rack-mini-profiler in development:

1
$ bundle exec rails g rack_profiler:install

Patching ActiveRecord
A typical web application spends a lot of time querying the database. rack_mini_profiler will detect the ORM that is available and apply patches to properly collect query statistics.

To make this work, declare the orm’s gem before declaring rack-mini-profiler in the Gemfile:

1
2
3
gem 'pg'
gem 'mongoid'
gem 'rack-mini-profiler'

If you wish to override this behavior, the environment variable RACK_MINI_PROFILER_PATCH is available.

1
2
3
4
export RACK_MINI_PROFILER_PATCH="pg,mongoid"
# or
export RACK_MINI_PROFILER_PATCH="false"
# initializers/rack_profiler.rb: SqlPatches.patch %w(mongo)

Flamegraphs

To generate flamegraphs:

add the stackprof gem to your Gemfile
visit a page in your app with ?pp=flamegraph

Memory Profiling

Memory allocations can be measured (using the memory_profiler gem) which will show allocations broken down by gem, file location, and class and will also highlight String allocations.

Add ?pp=profile-memory to the URL of any request while Rack::MiniProfiler is enabled to generate the report.

Additional query parameters can be used to filter the results.

1
2
3
4
memory_profiler_allow_files - filename pattern to include (default is all files)
memory_profiler_ignore_files - filename pattern to exclude (default is no exclusions)
memory_profiler_top - number of results per section (defaults to 50)
The allow/ignore patterns will be treated as regular expressions.

Example: ?pp=profile-memory&memory_profiler_allow_files=active_record|app

There are two additional pp options that can be used to analyze memory which do not require the memory_profiler gem

Use ?pp=profile-gc to report on Garbage Collection statistics
Use ?pp=analyze-memory to report on ObjectSpace statistics

Access control in non-development environments

rack-mini-profiler is designed with production profiling in mind. To enable that run Rack::MiniProfiler.authorize_request once you know a request is allowed to profile.

1
2
3
4
5
6
7
# inside your ApplicationController

before_action do
if current_user && current_user.is_admin?
Rack::MiniProfiler.authorize_request
end
end

If your production application is running on more than one server (or more than one dyno) you will need to configure rack mini profiler’s storage to use Redis or Memcache. See storage for information on changing the storage backend.


Note:

Out-of-the-box we will initialize the authorization_mode to :allow_authorized in production. However, in some cases we may not be able to do it:

  • If you are running in development or test we will not enable the explicit authorization mode

  • If you use require: false on rack_mini_profiler we are unlikely to be able to run the railtie

  • If you are running outside of rails we will not run the railtie


In those cases use:

1
Rack::MiniProfiler.config.authorization_mode = :allow_authorized

When deciding to fully profile a page mini profiler consults with the authorization_mode

By default in production we attempt to set the authorization mode to :allow_authorized meaning that end user will only be able to see requests where somewhere Rack::MiniProfiler.authorize_request is invoked.

In development we run in the :allow_all authorization mode meaning every request is profiled and displayed to the end user.

Snapshots Sampling

In a complex web application, it’s possible for a request to trigger rare conditions that result in poor performance. Mini Profiler ships with a feature to help detect those rare conditions and fix them. It works by enabling invisible profiling on one request every N requests, and saving the performance metrics that are collected during the request (a.k.a snapshot of the request) so that they can be viewed later. To turn this feature on, set the snapshot_every_n_requests config to a value larger than 0. The larger the value is, the less frequently requests are profiled.

Mini Profiler will exclude requests that are made to skipped paths (see skip_paths config below) from being sampled. Additionally, if profiling is enabled for a request that later finishes with a non-2xx status code, Mini Profiler will discard the snapshot and not save it (this behavior may change in the future).

See Snapshots Sampling - https://github.com/MiniProfiler/rack-mini-profiler#snapshots-sampling to learn more.

Configuration

Various aspects of rack-mini-profiler’s behavior can be configured when your app boots. For example in a Rails app, this should be done in an initializer: config/initializers/mini_profiler.rb

See Configuration - https://github.com/MiniProfiler/rack-mini-profiler#configuration to learn more.

References

[1] GitHub - MiniProfiler/rack-mini-profiler: Profiler for your development and production Ruby rack apps. - https://github.com/MiniProfiler/rack-mini-profiler

[2] rack-mini-profiler | RubyGems.org | your community gem host - https://rubygems.org/gems/rack-mini-profiler/

[3] Flame graphs in Ruby MiniProfiler - https://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler

[4] hschne/rails-mini-profiler: Performance profiling for Rails, made simple 🦔 - https://github.com/hschne/rails-mini-profiler

[5] tmm1/stackprof: a sampling call-stack profiler for ruby 2.2+ - https://github.com/tmm1/stackprof