Skip to content

Instantly share code, notes, and snippets.

@timraymond
Created May 1, 2015 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timraymond/8d7014e0c7804f0fe508 to your computer and use it in GitHub Desktop.
Save timraymond/8d7014e0c7804f0fe508 to your computer and use it in GitHub Desktop.
CanCan Benchmark
require 'bundler'
Bundler.require
require 'cancancan'
require 'allocation_tracer'
require 'benchmark/ips'
require 'objspace'
require 'pp'
def memprof(name)
GC.disable
before = `ps -o rss -p #{Process.pid}`.split("\n").last.to_i
trace = ObjectSpace::AllocationTracer.trace do
10_000.times do
yield
end
end
after = `ps -o rss -p #{Process.pid}`.split("\n").last.to_i
puts "[#{name}] Mem diff: #{(after - before).to_f/1024.0} MB"
#puts "[#{name}] Trace:"
#puts trace
#puts
GC.enable
GC.start
end
class Ability
include CanCan::Ability
def initialize
can [:read, :write], [:foo, :bar]
end
end
case ARGV.shift
when "--ips"
Benchmark.ips do |b|
b.report("Array#flatten") { CanCan::Rule.new(nil, [:read, :write], [:foo, :bar], nil, nil, false) }
b.report("Kernel#Array") { CanCan::Rule.new(nil, [:read, :write], [:foo, :bar], nil, nil, true) }
b.compare!
end
when "--match"
ability = Ability.new
rule = ability.send(:rules).first
rule.expanded_actions = ability.send(:expand_actions, rule.actions)
memprof("as-is") do
rule = ability.send(:rules).first
rule.expanded_actions = ability.send(:expand_actions, rule.actions)
rule.relevant?(:read, :bar)
end
else
memprof("Array#flatten") { CanCan::Rule.new(nil, [:read, :write], [:foo, :bar], nil, nil, false) }
memprof("Kernel#Array") { CanCan::Rule.new(nil, [:read, :write], [:foo, :bar], nil, nil, true) }
end
source 'http://rubygems.org'
gem 'cancancan', path: "~/github/cancancan"
gem 'allocation_tracer'
gem 'benchmark-ips'

I had to modify CanCan::Rule to be able to switch between the two code paths under test. I added a simple boolean flag as a final parameter and placed in a conditional like:

if use_flatten
  @actions = [actions].flatten
  @subjects = [subjects].flatten
else
  @actions = Array(actions)
  @subjects = Array(subjects)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment