Require Profiler
Require Profiler is a tool for profiling Ruby's code loading—Kernel#require, Kernel#require_relative, and Kernel#load. It captures the call tree, measures how long each file takes to load, and can export the results as a Speedscope-compatible JSON profile.
It's built on top of Require Hooks, so it works anywhere Require Hooks does (MRI/JRuby/TruffleRuby).
Installation
Add to your Gemfile:
gem "require-profiler"
Supported Ruby versions
- Ruby (MRI) >= 3.1
Usage
Wrap the code you want to profile with RequireProfiler.start and RequireProfiler.stop:
require "require_profiler"
RequireProfiler.start(output: "path/to/profile.txt")
require "my_app"
RequireProfiler.stop
Only require/load calls that happen between .start and .stop are captured. Put .start as early as possible (e.g., at the top of config/boot.rb or an entry-point script) to see the full loading tree.
RequireProfiler.stop returns a totals hash: {count: <number of files loaded>, time: <seconds>}.
Scoping via patterns
Use patterns: and exclude_patterns: to limit what gets profiled. Both accept globs as recognized by File.fnmatch and are passed through to Require Hooks:
RequireProfiler.start(
patterns: ["#{Dir.pwd}/app/**/*.rb", "#{Dir.pwd}/lib/**/*.rb"],
exclude_patterns: ["*/vendor/*"]
)
Output
RequireProfiler.start accepts the following keyword arguments:
output:—$stdout(default), any IO-like object, or a file path (string).format:—:text(default),:call_stack, or:json. Whenoutput:is a file path with a.jsonextension, the JSON format is picked automatically.patterns:/exclude_patterns:— see above.
Output formats
Text (default)
A human-readable indented tree, one line per file, with self+children duration in milliseconds:
lib/my_app.rb — 42.137ms
lib/my_app/config.rb — 3.211ms
lib/my_app/router.rb — 12.004ms
lib/my_app/routes.rb — 9.882ms
Paths are printed relative to Dir.pwd, Gem.dir, or Bundler.bundle_path when they match—so vendored gem loads stay readable.
Collapsed call stacks
RequireProfiler.start(output: "tmp/require-profile.txt", format: :call_stack)
Emits one line per stack in Brendan Gregg's collapsed format with per-frame self time in milliseconds. Pipe it to flamegraph.pl, inferno, or any tool that consumes folded stacks.
JSON / Speedscope
RequireProfiler.start(output: "tmp/require-profile.json")
# or:
RequireProfiler.start(output: io, format: :json)
Emits a profile that conforms to the Speedscope file format schema.
Note: Writing JSON straight to $stdout is not supported.
Using with Speedscope
Speedscope is an interactive flamegraph viewer that runs entirely in your browser (nothing is uploaded—the file is parsed locally).
- Generate a JSON profile:
RequireProfiler.start(output: "tmp/require-profile.json")
require "my_app"
RequireProfiler.stop
Open https://www.speedscope.app/ and drag-and-drop
tmp/require-profile.jsononto the page (or use the "Browse" button).Switch to the Left Heavy view to see which
requirechains cost the most time, and use Sandwich view to find individual files that show up repeatedly.
Prefer to stay local? Install the CLI and it will open a local viewer for you:
npm install -g speedscope
speedscope tmp/require-profile.json
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/palkan/require-profiler.
Credits
This gem is generated via newgem template by @palkan.
License
The gem is available as open source under the terms of the MIT License.