RailsMemoryProfiler

CI Gem Version Gem Downloads Ruby Rails codecov

Per-request memory allocation reports with a mountable dashboard UI. Fills the gap between the memory_profiler gem (terminal-only output, manual block wrapping) and having nowhere useful to browse results in a Rails app.

A Rack middleware captures object allocations for every request using GC.stat diffs. Results are stored in a thread-safe ring buffer and served through a mountable engine with a sortable, filterable dashboard.


Table of Contents


Installation

Add to your Gemfile:

gem "rails_memory_profiler", group: :development

Run the install generator:

bundle exec rails generate rails_memory_profiler:install

This creates config/initializers/rails_memory_profiler.rb with all options documented and prints mount instructions.

Mount the dashboard in config/routes.rb:

mount RailsMemoryProfiler::Engine, at: "/rails/memory"

Then visit /rails/memory/reports to see per-request allocation data.

↑ Back to top


Dashboard

The index view shows a sortable table of captured requests. Click any row to open the detail view for that request.

Columns: Path, Controller#Action, Allocated Objects (colour-coded), Retained Objects, Duration (ms), Recorded At.

Use the controller filter to narrow the table down to a specific controller without a page reload.

↑ Back to top


Configuration

All options and their defaults:

Option Default Description
enabled true in development Enable/disable request profiling
sample_rate 1 Profile every Nth request (1 = every request)
store_size 100 Max reports in the ring buffer; oldest are evicted when full
dashboard_enabled true in development Enable the dashboard endpoint
min_allocated_objects 0 Skip requests that allocate fewer objects than this
ignore_paths [] Additional paths to skip — strings (prefix) or regexes (the dashboard's own mount path is auto-ignored)
ignore_controllers [] Controller names to skip (e.g. "rails/health")
detailed_reports false Capture full MemoryProfiler.report breakdowns; requires gem "memory_profiler" in your Gemfile
detailed_sample_rate 10 When detailed_reports is enabled, capture a full report every Nth profiled request
notifiers [] Array of objects responding to #call(report); called after each report is stored
log_file nil Path to append JSON-serialized reports (one per line); shortcut for Notifiers::FileLogger
raise_on_allocation_spike nil Raise AllocationSpikeError when allocated_objects exceeds this threshold

Example:

RailsMemoryProfiler.configure do |config|
  config.sample_rate           = 5
  config.min_allocated_objects = 1_000
  config.ignore_paths          = ["/up"]   # dashboard mount path is auto-ignored
  config.ignore_controllers    = ["rails/health"]
  config.notifiers             = [RailsMemoryProfiler::Notifiers::Console.new]
  config.log_file              = Rails.root.join("log/memory_profiler.jsonl")
end

Test helpers

# Plain Ruby / shared utility
require "rails_memory_profiler/test_helper"

count = RailsMemoryProfiler::TestHelper.capture_allocations { MyClass.new }
RailsMemoryProfiler::TestHelper.assert_allocations_below(500) { MyClass.new }
# raises Minitest::Assertion when Minitest is loaded, RuntimeError otherwise

# Minitest — adds assert_allocates_fewer_than to all Minitest::Test subclasses
require "rails_memory_profiler/minitest_matchers"

assert_allocates_fewer_than(500) { MyClass.new }
assert_allocates_fewer_than(500, "MyClass allocates too much") { MyClass.new }

# RSpec
require "rails_memory_profiler/rspec_matchers"

expect { MyClass.new }.to allocate_fewer_than(500)

↑ Back to top


Contributing

Bug reports and pull requests are welcome on GitHub.

↑ Back to top


License

The gem is available as open source under the terms of the MIT License.

↑ Back to top