diff --git a/.github/workflows/build.yml b/.github/workflows/specs.yaml similarity index 98% rename from .github/workflows/build.yml rename to .github/workflows/specs.yaml index 6c409d7..a359244 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/specs.yaml @@ -1,4 +1,4 @@ -name: CI Test +name: Specs on: [ push ] jobs: build: diff --git a/.github/workflows/standardrb.yaml b/.github/workflows/standard.yaml similarity index 100% rename from .github/workflows/standardrb.yaml rename to .github/workflows/standard.yaml diff --git a/README.md b/README.md index 99be61c..8440bbc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,16 @@ # Singed + +[![Gem Version](https://badge.fury.io/rb/singed.svg)](https://badge.fury.io/rb/singed) ![CI](https://github.com/rubyatscale/singed/actions/workflows/specs.yaml/badge.svg?event=push) ![Lint](https://github.com/rubyatscale/singed/actions/workflows/standard.yaml/badge.svg?event=push) + + Singed makes it easy to get a flamegraph anywhere in your code base. It wraps profiling your code with [stackprof](https://github.com/tmm1/stackprof) or [rbspy](https://github.com/rbspy/rbspy), and then launching [speedscope](https://github.com/jlfwong/speedscope) to view it. +But why would you want to do this? At least a couple of reasons: + +- you have code that you either feel, think, or KNOW is slow +- you are curious about how some code actually runs + ## Installation Add to `Gemfile`: @@ -16,7 +25,7 @@ Then run `npm install -g speedscope` ## Usage -Simplest is calling with a block: +The simplest way is to wrap your code with a block ```ruby flamegraph { @@ -30,7 +39,7 @@ Flamegraphs are saved for later review to `Singed.output_directory`, which is `t Singed.output_directory = "tmp/slowness-exploration" ``` -### Blockage +### Block form If you are calling it in a loop, or with different variations, you can include a label on the filename: ```ruby @@ -39,7 +48,7 @@ flamegraph("rspec") { } ``` -You can also skip opening speedscope automatically: +You can also skip opening speedscope in a browser automatically: ```ruby flamegraph(open: false) { @@ -47,9 +56,22 @@ flamegraph(open: false) { } ``` -### RSpec +##### Options + +`flamegraph` takes some of the options that [stackprof]() does: -If you are using RSpec, you can use the `flamegraph` metadata to capture it for you. +- `ignore_gc: true`: if your profiled code is very memory heavy, the garbage collection can make it harder to read. ignoring gc can make it more readable, but it's also a sign to use [memory_profiler](https://github.com/SamSaffron/memory_profiler). +- `interval: 1000` (in ms): how frequently to sample. for very small + +Plus some of its own: + +- `label: "your-description"`: a label to include in the filename +- `open: false`: don't try to `open` the flamegraph in a browser +- `io: File.open("your-output")` where to write the output, defaults to `$stdout` + +#### RSpec + +If you are using RSpec, you can use the `flamegraph` metadata to capture it for you. This [RSpec::Core::Hooks#around](https://rubydoc.info/gems/rspec-core/RSpec%2FCore%2FHooks:around), so focuses only on code inside the example block. ```ruby # make sure this is required at somepoint, like in a spec/support file! @@ -62,7 +84,7 @@ RSpec.describe YourClass do end ``` -### Controllers +#### Controllers If you want to capture a flamegraph of a controller action, you can call it like: @@ -76,9 +98,9 @@ class EmployeesController < ApplicationController end ``` -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). +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 +#### 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: @@ -90,7 +112,7 @@ PROTIP: use Chrome Developer Tools to record network activity, and copy requests This can also be enabled to always run by setting `SINGED_MIDDLEWARE_ALWAYS_CAPTURE=1` in the environment. -### Command Line +#### Command Line There is a `singed` command line you can use that will record a flamegraph from the entirety of a command run: @@ -101,6 +123,12 @@ $ bundle exec singed -- bin/rails runner 'Model.all.to_a' The flamegraph is opened afterwards. +## How to read a flamegraph + +You've generated a flamegraph, now what? That's a great question. Here's some resources for getting started: + +- [technicalpickles/flamegraph-lighting-talk](https://github.com/technicalpickles/flamegraph-lighting-talk) +- [Pairin' with Aaron: Flamegraphs and App Performance - YouTube](https://www.youtube.com/watch?v=9nvX3OHykGQ) ## Limitations