Skip to content

Repository files navigation

Singed

Singed makes it easy to get a flamegraph anywhere in your code base. It wraps profiling your code with stackprof or rbspy, and then launching speedscope to view it.

Installation

Add to Gemfile:

gem"singed"

Then run bundle install

Then run npm install -g speedscope

Usage

Simplest is calling with a block:

flamegraph{# your code here}

Flamegraphs are saved for later review to Singed.output_directory, which is tmp/speedscope on Rails. You can adjust this like:

Singed.output_directory="tmp/slowness-exploration"

Blockage

If you are calling it in a loop, or with different variations, you can include a label on the filename:

flamegraph("rspec"){# your code here}

You can also skip opening speedscope automatically:

flamegraph(open: false){# your code here}

Explicit start and stop

You can also start and stop the flamegraph explicitly:

# config/boot.rbrequire"singed"Singed.output_directory ||= Dir.pwd + "/tmp/speedscope"Singed.start# Let some code to run here...# and then stop the flamegraph with e.g. rails runner 'Singed.stop'flamegraph=Singed.stop# The flamegraph is saved to the output directory# Open it with your browser:flamegraph.open

Note that Singed.start can't be run multiple times in parallel, instantiate multiple Singed::Flamegraph objects instead and call start on them.

RSpec

If you are using RSpec, you can use the flamegraph metadata to capture it for you.

# make sure this is required at somepoint, like in a spec/support file!require'singed/rspec'RSpec.describeYourClassdoit"is slow :(",flamegraph: truedo# your code hereendend

Controllers

If you want to capture a flamegraph of a controller action, you can call it like:

classEmployeesController < ApplicationControllerflamegraph:showdefshow# your code hereendend

This won't catch the entire request though, just once it's been routed to controller and a response has been served (ie no middleware).

Rack/Rails requests

To capture the whole request, there is a middleware which checks for the X-Singed header to be 'true'. With curl, you can do this like:

curl -H 'X-Singed: true' https://localhost:3000

PROTIP: use Chrome Developer Tools to record network activity, and copy requests as a curl command. Add -H 'X-Singed: true' to it, and you get flamegraphs!

This can also be enabled to always run by setting SINGED_MIDDLEWARE_ALWAYS_CAPTURE=1 in the environment.

Sidekiq

If you are using Sidekiq, you can use the Singed::Sidekiq::ServerMiddleware to capture flamegraphs for you.

require"singed/sidekiq"Sidekiq.configure_serverdo |config|
config.server_middlewaredo |chain|
chain.addSinged::Sidekiq::ServerMiddlewareendend

To capture flamegraphs for all jobs, you can set the SINGED_MIDDLEWARE_ALWAYS_CAPTURE environment variable to true the same way as the Rack middleware.

To capture flamegraphs for a specific job, you can set the x-singed key in the job payload to true.

MyJob.set("x-singed"=>true).perform_async

Or define a capture_flamegraph? method on the job class:

classMyJobdefself.capture_flamegraph?(payload)payload["flamegraph"]endend

Command Line

There is a singed command line you can use that will record a flamegraph from the entirety of a command run:

$ bundle binstub singed # if you want to be able to call it like bin/singed
$ bundle exec singed -- bin/rails runner 'Model.all.to_a'

The flamegraph is opened afterwards.

Limitations

When using the auto-opening feature, it's assumed that you are have a browser available on the same host you are profiling code.

The open command is expected to be available.

Alternatives

About

Get a flamegraph anywhere in your code base. Powered by stackprof, rbspy, and speedscope

Topics

Resources

Stars

421 stars

Watchers

8 watching

Forks

Releases

Packages

Used by

Contributors

Languages