Created
August 24, 2023 13:30
-
-
Save technicalpickles/4a4ae6a9e2c42963af43a89f75e768fe to your computer and use it in GitHub Desktop.
AbstractController::Base#action_methods benchmark
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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