Speed up policy lookups in DeclarativePolicy
What does this MR do and why?
Add a global cache to cache subject's mapping to their policy classes.
This patches will be upstreamed to declarative-policy gem soonish.
See gitlab-org/ruby/gems/declarative-policy#30 and !119924 (merged).
How to set up and validate locally
Heavily inspired by !119924 (merged).
Benchmark code
# frozen_string_literal: true
require "./config/environment"
Rails.configuration.eager_load_namespaces.each(&:eager_load!)
puts "Application is loaded."
require 'benchmark/ips'
class Project2 < Project
def self.declarative_policy_class
:ProjectPolicy
end
end
user = User.first
subject_1 = Project.first
subject_2 = Project2.first
Benchmark.ips do |b|
b.report('implicit') do
DeclarativePolicy.policy_for(user, subject_1)
end
b.report('explicit') do
DeclarativePolicy.policy_for(user, subject_2)
end
b.compare!
end
Before
Application is loaded.
Warming up --------------------------------------
implicit 463.000 i/100ms
explicit 17.589k i/100ms
Calculating -------------------------------------
implicit 4.232k (±27.7%) i/s - 18.520k in 5.073017s
explicit 163.059k (± 6.6%) i/s - 826.683k in 5.092063s
Comparison:
explicit: 163058.5 i/s
implicit: 4232.2 i/s - 38.53x slower
After
Application is loaded.
Warming up --------------------------------------
implicit 16.562k i/100ms
explicit 15.042k i/100ms
Calculating -------------------------------------
implicit 139.730k (± 8.8%) i/s - 695.604k in 5.020544s
explicit 124.751k (± 8.7%) i/s - 631.764k in 5.100487s
Comparison:
implicit: 139730.3 i/s
explicit: 124750.5 i/s - same-ish: difference falls within error
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
Edited by Peter Leitzen