Skip to content

Instantly share code, notes, and snippets.

@technicalpickles
Created August 24, 2023 13:30
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 technicalpickles/4a4ae6a9e2c42963af43a89f75e768fe to your computer and use it in GitHub Desktop.
Save technicalpickles/4a4ae6a9e2c42963af43a89f75e768fe to your computer and use it in GitHub Desktop.
AbstractController::Base#action_methods benchmark
# frozen_string_literal: true
require 'action_controller'
require 'benchmark/ips'
require 'benchmark/memory'
puts "ActionPack.version = #{ActionPack.version}"
module Actions
def foo
end
def bar
end
def baz
end
end
class Current < ActionController::Base
include Actions
def action_methods
@action_methods ||= begin
# All public instance methods of this class, including ancestors
methods = (public_instance_methods(true) -
# Except for public instance methods of Base and its ancestors
internal_methods +
# Be sure to include shadowed public instance methods of this class
public_instance_methods(false))
methods.map!(&:to_s)
methods.to_set
end
end
end
class Refactored < ActionController::Base
include Actions
class << self
def action_methods
@action_methods ||= begin
methods = Set.new
methods.merge(public_instance_methods(true))
methods.subtract(internal_methods)
methods.merge(public_instance_methods(false))
methods.map!(&:to_s)
end
end
end
end
class Refactored2 < ActionController::Base
include Actions
class << self
def action_methods
@action_methods ||= begin
Set.new(public_instance_methods(true))
.subtract(internal_methods)
.merge(public_instance_methods(false))
.map!(&:to_s)
end
end
end
end
class Refactored3 < ActionController::Base
include Actions
class << self
def action_methods
@action_methods ||= begin
methods = public_instance_methods(true) - internal_methods
methods.concat(public_instance_methods(false))
methods.map!(&:to_s)
methods.to_set
end
end
end
end
class Refactored4 < ActionController::Base
include Actions
class << self
def action_methods
@action_methods ||= begin
methods = public_instance_methods(true)
internal_methods = internal_methods()
methods.reject! {|m| internal_methods.include?(m) }
methods.concat(public_instance_methods(false))
methods.map!(&:to_s)
methods.to_set
end
end
end
end
Benchmark.memory do |x|
x.report("original") do
Current.clear_action_methods!
Current.action_methods
end
x.report("refactored") do
Refactored.clear_action_methods!
Refactored.action_methods
end
x.report("refactored2") do
Refactored2.clear_action_methods!
Refactored2.action_methods
end
x.report("refactored3") do
Refactored3.clear_action_methods!
Refactored3.action_methods
end
x.report("refactored4") do
Refactored4.clear_action_methods!
Refactored4.action_methods
end
x.compare!
end
Benchmark.ips do |x|
x.report("original") do
Current.clear_action_methods!
Current.action_methods
end
x.report("refactored") do
Refactored.clear_action_methods!
Refactored.action_methods
end
x.report("refactored2") do
Refactored2.clear_action_methods!
Refactored2.action_methods
end
x.report("refactored3") do
Refactored3.clear_action_methods!
Refactored3.action_methods
end
x.report("refactored4") do
Refactored4.clear_action_methods!
Refactored4.action_methods
end
x.compare! order: :baseline
end
ActionPack.version = 7.0.6
Calculating -------------------------------------
original 8.352k memsize ( 208.000 retained)
22.000 objects ( 2.000 retained)
6.000 strings ( 0.000 retained)
refactored 7.704k memsize ( 208.000 retained)
10.000 objects ( 2.000 retained)
3.000 strings ( 0.000 retained)
refactored2 7.704k memsize ( 208.000 retained)
10.000 objects ( 2.000 retained)
3.000 strings ( 0.000 retained)
refactored3 7.616k memsize ( 408.000 retained)
11.000 objects ( 7.000 retained)
3.000 strings ( 3.000 retained)
refactored4 7.576k memsize ( 3.944k retained)
10.000 objects ( 7.000 retained)
3.000 strings ( 3.000 retained)
Comparison:
refactored4: 7576 allocated
refactored3: 7616 allocated - 1.01x more
refactored: 7704 allocated - 1.02x more
refactored2: 7704 allocated - 1.02x more
original: 8352 allocated - 1.10x more
Warming up --------------------------------------
original 2.292k i/100ms
refactored 1.204k i/100ms
refactored2 1.218k i/100ms
refactored3 2.481k i/100ms
refactored4 540.000 i/100ms
Calculating -------------------------------------
original 23.420k (± 1.1%) i/s - 119.184k in 5.089625s
refactored 12.335k (± 0.7%) i/s - 62.608k in 5.076042s
refactored2 12.345k (± 0.7%) i/s - 62.118k in 5.032163s
refactored3 24.881k (± 1.0%) i/s - 126.531k in 5.085861s
refactored4 5.415k (± 1.1%) i/s - 27.540k in 5.086904s
Comparison:
original: 23419.7 i/s
refactored3: 24881.3 i/s - 1.06x faster
refactored2: 12344.8 i/s - 1.90x slower
refactored: 12334.7 i/s - 1.90x slower
refactored4: 5414.5 i/s - 4.33x slower
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment