• Stars
    star
    258
  • Rank 158,189 (Top 4 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 11 years ago
  • Updated over 11 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Profile Ruby code and find out exactly how slow it runs.

Pilfer

Profile Ruby code and find out exactly how slow it runs.

Pilfer uses rblineprof to measure how long each line of code takes to execute and the number of times it was called.

Pilfer Profile.png

Take a look at some Pilfer profiles of the Bundler API site.

Installation

Using with Bundler is as simple as adding pilfer to your Gemfile.

gem 'pilfer', '~> 1.0.0'

Or install it locally like any other gem.

$ gem install pilfer

Usage

Profile a block of code saving the report to the file profile.log.

require 'pilfer'

reporter = Pilfer::Logger.new('pilfer.log')
profiler = Pilfer::Profiler.new(reporter)
profiler.profile('bubble sorting') do
  array = (0..100).to_a.shuffle
  bubble_sort array
end

Profile your Rack or Rails app using Pilfer::Middleware.

reporter = Pilfer::Logger.new('pilfer.log')
profiler = Pilfer::Profiler.new(reporter)
use Pilfer::Middleware, :profiler => profiler

The profile report consists of the wall time and call count for each line of code executed along with the total wall and CPU times for each file.

Profile start="2013-05-12 00:41:16 UTC" description="bubble sorting"
/Users/Larry/Sites/pilfer/sort.rb wall_time=42.5ms cpu_time=29.7ms
                   | require 'pilfer'
                   |
                   | def bubble_sort(container)
    42.5ms (    1) |   loop do
                   |     swapped = false
    42.3ms (   94) |     (container.size-1).times do |i|
    10.2ms ( 9400) |       if (container[i] <=> container[i+1]) == 1
     6.2ms ( 5092) |         container[i], container[i+1] = container[i+1], container[i] # Swap
                   |         swapped = true
                   |       end
                   |     end
                   |     break unless swapped
                   |   end
                   |   container
                   | end
                   |
                   | reporter = Pilfer::Logger.new($stdout)
                   | profiler = Pilfer::Profiler.new(reporter)
                   | profiler.profile_files_matching(/sort\.rb/, 'bubble sorting') do
     0.1ms (    3) |   array = (0..100).to_a.shuffle
    42.5ms (    1) |   bubble_sort array
                   | end

Step 1: Create a reporter

Decide how you want line profiles to be reported. Profiles can be sent to a pilfer-server or written to a file path or IO object.

# Send reports to a pilfer-server
reporter = Pilfer::Server.new('https://pilfer.com', 'my-pilfer-server-token')

# Append reports to a file
reporter = Pilfer::Logger.new('pilfer.log')

# Print reports to standard out
reporter = Pilfer::Logger.new($stdout)

The absolute path to each profiled file is used in the report. Set the path to the application root with :app_root to have it trimmed from reported file paths.

reporter = Pilfer::Logger.new('pilfer.log')
# Profile start=2013-05-02 14:17:26 UTC
# /Sites/bundler-api/lib/bundler-api/web.rb wall_time=1009.5ms cpu_time=0.5ms
# ...

reporter = Pilfer::Logger.new('pilfer.log', :app_root => '/Sites/bundler-api/')
# Profile start=2013-05-02 14:17:26 UTC
# lib/bundler-api/web.rb wall_time=1009.5ms cpu_time=0.5ms
# ...

Step 2: Create a profiler

A Profiler runs the line profiler and sends it to a reporter. Create one passing the reporter created in the previous step.

profiler = Pilfer::Profiler.new(reporter)

Step 3: Profile a block of code

Use Profiler#profile to profile a block of code. Optionally, provide a description of the code being profiling.

profiler.profile('bubble sorting') do
  array = (0..100).to_a.shuffle
  bubble_sort array
end

Every file that's executed by the block including code outside the application like gems and standard libraries will be included in the profile. Use #profile_files_matching to limit profiling to files whose paths match a regular expression.

# Only profile Rails models
matcher = %r{^#{Regexp.escape(Rails.root.to_s)}/app/models}
profiler.profile_files_matching(matcher, 'User.find_by_email') do
  User.find_by_email('[email protected]')
end

Additional arguments to #profile and #profile_files_matching will be passed to the reporter. The Pilfer::Server reporter, for example, can submit profiles asynchronously.

profiler.profile('bubble sorting', :submit => :async) do
  array = (0..100).to_a.shuffle
  bubble_sort array
end

Extras

Pilfer Server

Pilfer Server is your own, personal service for collecting and viewing line profiles gathered by Pilfer. Follow the Pilfer Server setup instructions to stand up a new server.

reporter = Pilfer::Server.new('https://pilfer.com', 'my-pilfer-server-token')
profiler = Pilfer::Profiler.new(reporter)
profiler.profile('bubble sorting') do
  array = (0..100).to_a.shuffle
  bubble_sort array
end

Rack Middleware

Profile your entire Rack or Rails app using Pilfer::Middleware. Pass it a Profiler created with a reporter as normal.

reporter = Pilfer::Server.new('https://pilfer.com', 'my-pilfer-server-token')
profiler = Pilfer::Profiler.new(reporter)
use Pilfer::Middleware, :profiler => profiler

Restrict profiling to files matching a regular expression using the :files_matching option. This calls Profiler#profile_files_matching using the given regular expression.

matcher = %r{^#{Regexp.escape(Rails.root.to_s)}/(app|config|lib|vendor/plugin)}
use Pilfer::Middleware, :profiler     => profiler,
                        :file_matcher => matcher

You almost certainly don't want to profile every request. Provide a block to determine if a profile should be run on the incoming request.

use Pilfer::Middleware, :profiler => profiler do
  # Profile 1% of requests.
  rand(100) == 1
end

The Rack environment is available to allow profiling on demand.

# Profile requests containing the query string ?profile=true
use Pilfer::Middleware, :profiler => profiler do |env|
  env["QUERY_STRING"].include? 'profile=true'
end

# Profile requests containing a header whose value matches a secret
use Pilfer::Middleware, :profiler => profiler do |env|
  env['HTTP_PROFILE_AUTHORIZATION'] == 'super-secret'
end

Supported Ruby Versions

This library is tested against the following Ruby versions.

  • MRI 1.9.3
  • MRI 1.8.7
  • REE

If you need a specific version supported, open and issue or send a pull request.

License

The MIT License (MIT)

Copyright (c) 2013 Eric Lindvall and Larry Marburger. See LICENSE for details.

More Repositories

1

metriks

An experimental library to instrument ruby
Ruby
479
star
2

gistr

A simple tool to post a Gist on tumblr
Ruby
70
star
3

metriksd

Server component to receive metrics from metriks
Ruby
23
star
4

pilfer-server

Collect and display Ruby line profiles reported from pilfer.
Ruby
21
star
5

metriks_log_webhook

An experimental webhook for an experimental metrics library
Ruby
17
star
6

syslog_protocol

syslog protocol for ruby
Ruby
15
star
7

whisper-rb

A ruby wrapper on the Whisper database from Graphite
Python
14
star
8

rubyrrdtool

RubyRRDtool provides ruby bindings for RRDtool functions (via librrd), with functionality comparable to the native RRDtool perl bindings.
C
14
star
9

p2met

Papertrail l2met-style webhook
Ruby
12
star
10

flickvimeo

A simple tool to use AirFlick to send Vimeo videos to your AppleTV
Ruby
8
star
11

click_to_call

A simple Adhearsion click-to-call example
Ruby
7
star
12

metriks-librato_metrics

Librato Metrics reporter for Metriks
Ruby
7
star
13

papertrail_prowl_webhook

Papertrail webhook to send alerts to Prowl for iOS push notification
Ruby
6
star
14

sevenscale-scout-plugins

A bunch of plugins for scout
Ruby
6
star
15

metriksd_reporter

A reporter to send metrics from metriks to metriks_server
Ruby
6
star
16

section_one

A multi-service metrics viewer inspired by FiveRuns Dash
Ruby
5
star
17

tender_summary

A simple tool to email your pending Tender discussions
Ruby
5
star
18

gemist

Capistrano recipes for gem installation
Ruby
5
star
19

librato_metrics_client

A purely experimental metrics client
Ruby
4
star
20

phoenix_status

A little AGI to speak the current MarsPhoenix Twitter status
Ruby
4
star
21

papertrail_librato_webhook

Basic webhook to send metrics to Silverline from Papertrail
Ruby
4
star
22

docker-srtla

Docker container for running srtla
Shell
3
star
23

app_swift

A mirror of the asterisk swift app written by Darren Sessions
C
3
star
24

signal

Signal bot for #jruby
Ruby
2
star
25

nested-layouts

Rails 2.1.1 broke nested-layouts, this is the "fixed" version
Ruby
2
star
26

dashup

Simple greasemonkey fun for dash.fiveruns.com
JavaScript
2
star
27

dharma

Ruby futures and promises library in the spirit of Scala
Ruby
2
star
28

nested_scenarios

FixtureScenarios, FixtureScenariosBuilder, Yaml and Ruby in one big mix for Rails.
Ruby
2
star
29

bunny-ext

Reliable socket timeouts for the Bunny amqp gem
Ruby
1
star
30

jetson-kernel-build

Make a custom kernel for the Jetson Nano
Dockerfile
1
star
31

activerecord-mysql2-adapter

An ActiveRecord 2.3 adapter for the mysql2 gem
1
star
32

appconference

Fork of http://sourceforge.net/projects/appconference
C
1
star
33

solar_power

Display solar power generation on a LaMetric
Ruby
1
star
34

syslog-ng-3.3

C
1
star
35

multi_field_group_by

Adds functionality from http://rails.lighthouseapp.com/projects/8994/tickets/120 as a plugin
Ruby
1
star
36

metriks-graphite

Graphite reporter for metriks
Ruby
1
star
37

github-flavored-markdown

JavaScript
1
star