Skip to content

Instantly share code, notes, and snippets.

@printercu
Last active August 29, 2015 14:05
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 printercu/622037a07431e5c45d53 to your computer and use it in GitHub Desktop.
Save printercu/622037a07431e5c45d53 to your computer and use it in GitHub Desktop.
Benchmarking thread-safe class_attribute
require 'benchmark'
require 'active_support/all'
class Class
def class_attribute2(*attrs)
options = attrs.extract_options!
instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
instance_predicate = options.fetch(:instance_predicate, true)
attrs.each do |name|
define_singleton_method(name) { nil }
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
ivar = "@#{name}"
define_singleton_method name do
if instance_variable_defined?(ivar)
instance_variable_get(ivar)
else
superclass.send(name) rescue nil
end
end
define_singleton_method "#{name}=" do |val|
instance_variable_set(ivar, val)
if singleton_class?
class_eval do
define_method name do
if instance_variable_defined?(ivar)
instance_variable_get ivar
else
singleton_class.public_send name
end
end
end
end
val
end
if instance_reader
define_method(name) do
if instance_variable_defined?(ivar)
instance_variable_get ivar
else
self.class.public_send name
end
end
define_method("#{name}?") { !!public_send(name) } if instance_predicate
end
attr_writer name if instance_writer
end
end
end
class Grand
class_attribute :value
class_attribute2 :value2
end
class Parent < Grand
end
class Child < Parent
end
n = 1_000_000
singleton = Grand.new.singleton_class
Benchmark.bmbm do |b|
b.report(:setter_orig) { n.times { |i| Grand.value = 1 } }
b.report(:setter_patch) { n.times { |i| Grand.value2 = 1 } }
b.report(:singleton_setter_orig) { n.times { |i| Grand.value = 1 } }
b.report(:singleton_setter_patch) { n.times { |i| Grand.value2 = 1 } }
b.report(:getter_direct_orig) { n.times { |i| Grand.value } }
b.report(:getter_direct_patch) { n.times { |i| Grand.value2 } }
b.report(:getter_child_orig) { n.times { |i| Parent.value } }
b.report(:getter_child_patch) { n.times { |i| Parent.value2 } }
b.report(:getter_grand_child_orig) { n.times { |i| Child.value } }
b.report(:getter_grand_child_patch) { n.times { |i| Child.value2 } }
end
@printercu
Copy link
Author

Rehearsal ------------------------------------------------------------
setter_orig                4.320000   0.040000   4.360000 (  4.374553)
setter_patch               0.460000   0.000000   0.460000 (  0.461775)
singleton_setter_orig      4.390000   0.020000   4.410000 (  4.435148)
singleton_setter_patch     0.540000   0.000000   0.540000 (  0.550230)
getter_direct_orig         0.160000   0.000000   0.160000 (  0.157842)
getter_direct_patch        0.540000   0.010000   0.550000 (  0.543397)
getter_child_orig          0.160000   0.000000   0.160000 (  0.157356)
getter_child_patch         0.860000   0.000000   0.860000 (  0.861472)
getter_grand_child_orig    0.160000   0.000000   0.160000 (  0.162033)
getter_grand_child_patch   1.330000   0.000000   1.330000 (  1.324208)
-------------------------------------------------- total: 12.990000sec

                               user     system      total        real
setter_orig                4.320000   0.030000   4.350000 (  4.369558)
setter_patch               0.450000   0.000000   0.450000 (  0.448362)
singleton_setter_orig      4.320000   0.030000   4.350000 (  4.380453)
singleton_setter_patch     0.480000   0.000000   0.480000 (  0.485239)
getter_direct_orig         0.150000   0.000000   0.150000 (  0.157387)
getter_direct_patch        0.460000   0.000000   0.460000 (  0.457611)
getter_child_orig          0.160000   0.000000   0.160000 (  0.156768)
getter_child_patch         0.950000   0.000000   0.950000 (  0.947013)
getter_grand_child_orig    0.160000   0.000000   0.160000 (  0.162784)
getter_grand_child_patch   1.280000   0.000000   1.280000 (  1.288407)

@printercu
Copy link
Author

Benchmark.ips do |b|
  b.report('set_orig')  { Grand.value = 1 }
  b.report('set_patch') { Grand.value2 = 1 }
  b.compare!
end

Benchmark.ips do |b|
  b.report('singleton_set_orig')  { Grand.value = 1 }
  b.report('singleton_set_patch') { Grand.value2 = 1 }
  b.compare!
end

Benchmark.ips do |b|
  b.report('get_direct_orig')  { Grand.value }
  b.report('get_direct_patch') { Grand.value2 }

  b.report('get_child_orig')  { Parent.value }
  b.report('get_child_patch') { Parent.value2 }

  b.report('get_gr_child_orig')  { Child.value }
  b.report('get_gr_child_patch') { Child.value2 }

  b.compare!
end
Calculating -------------------------------------
            set_orig     11457 i/100ms
           set_patch     21204 i/100ms
-------------------------------------------------
            set_orig   231021.6 (±21.0%) i/s -    1111329 in   5.040793s
           set_patch  1805810.9 (±13.3%) i/s -    8820864 in   4.999600s

Comparison:
           set_patch:  1805810.9 i/s
            set_orig:   231021.6 i/s - 7.82x slower

Calculating -------------------------------------
  singleton_set_orig     11859 i/100ms
 singleton_set_patch     22527 i/100ms
-------------------------------------------------
  singleton_set_orig   234758.3 (±19.7%) i/s -    1138464 in   5.047345s
 singleton_set_patch  1838948.8 (±12.2%) i/s -    9010800 in   4.998438s

Comparison:
 singleton_set_patch:  1838948.8 i/s
  singleton_set_orig:   234758.3 i/s - 7.83x slower

Calculating -------------------------------------
     get_direct_orig     28707 i/100ms
    get_direct_patch     23137 i/100ms
      get_child_orig     27768 i/100ms
     get_child_patch     21162 i/100ms
   get_gr_child_orig     28401 i/100ms
  get_gr_child_patch     18447 i/100ms
-------------------------------------------------
     get_direct_orig  4496212.6 (±11.5%) i/s -   22018269 in   4.994925s
    get_direct_patch  1818551.3 (±12.2%) i/s -    8907745 in   4.999383s
      get_child_orig  4507921.5 (±11.7%) i/s -   21992256 in   4.996994s
     get_child_patch  1020330.4 (±11.9%) i/s -    5015394 in   5.004444s
   get_gr_child_orig  4427673.4 (±13.3%) i/s -   21499557 in   4.994001s
  get_gr_child_patch   718534.3 (±10.5%) i/s -    3541824 in   4.998001s

Comparison:
      get_child_orig:  4507921.5 i/s
     get_direct_orig:  4496212.6 i/s - 1.00x slower
   get_gr_child_orig:  4427673.4 i/s - 1.02x slower
    get_direct_patch:  1818551.3 i/s - 2.48x slower
     get_child_patch:  1020330.4 i/s - 4.42x slower
  get_gr_child_patch:   718534.3 i/s - 6.27x slower

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment