pokonski/access_granted — pull request #1 by farnoy (2013-10-12 14:48:27+00:00)
Title: optimize lookup

* store a hash for quick indexing into permissions by action
* remove complicated logic in matches_subject_class?
* inline logic for matches_subject?

## Benchmarks
Before
```
Total: 263 samples
89 33.8% 33.8% 250 95.1% Array#select
61 23.2% 57.0% 66 25.1% AccessGranted::Permission#matches_action?
52 19.8% 76.8% 161 61.2% AccessGranted::Permission#relevant?
20 7.6% 84.4% 43 16.3% AccessGranted::Permission#matches_subject?
20 7.6% 92.0% 21 8.0% String#==
10 3.8% 95.8% 10 3.8% garbage_collector
5 1.9% 97.7% 5 1.9% Symbol#==
2 0.8% 98.5% 2 0.8% Kernel#class
1 0.4% 98.9% 251 95.4% AccessGranted::Role#relevant_permissions
1 0.4% 99.2% 1 0.4% Enumerable#detect
1 0.4% 99.6% 253 96.2% Integer#times
1 0.4% 100.0% 1 0.4% Kernel#respond_to_missing?
0 0.0% 100.0% 252 95.8% AccessGranted::Role#can?
0 0.0% 100.0% 253 96.2% Benchmark#measure
0 0.0% 100.0% 253 96.2% Benchmark.measure
```

After
```
Total: 78 samples
29 37.2% 37.2% 48 61.5% AccessGranted::Permission#matches_subject?
23 29.5% 66.7% 71 91.0% AccessGranted::Role#relevant_permissions
14 17.9% 84.6% 17 21.8% String#==
6 7.7% 92.3% 6 7.7% garbage_collector
3 3.8% 96.2% 3 3.8% Kernel#respond_to_missing?
2 2.6% 98.7% 2 2.6% Kernel#class
1 1.3% 100.0% 72 92.3% AccessGranted::Role#can?
0 0.0% 100.0% 72 92.3% Benchmark#measure
0 0.0% 100.0% 72 92.3% Benchmark.measure
0 0.0% 100.0% 72 92.3% Integer#times
```

code:
```ruby
require 'bundler'
Bundler.setup
require_relative 'lib/access_granted'
require 'benchmark'

role = AccessGranted::Role.new 'test', 0

stubs = [:edit, :create, :manage, :delete]
names = ('A'..'D').to_a

module TestPool
end

require 'perftools'
measurement = nil
PerfTools::CpuProfiler.start("/tmp/da_bench") do
measurement = Benchmark.measure do
names.permutation.each do |perm|
name = perm.join
TestPool.const_set name, Struct.new(:nvm)
stubs.each do |stub|
role.can stub, name
end
end

puts TestPool.constants.count * stubs.size

query = TestPool::DCBA.new
100000.times { role.can? :create, query }
end
end
```