Skip to content

Commit

Permalink
RequestStore#fetch without &block
Browse files Browse the repository at this point in the history
&block in method definitions creates additional proc which consumes more time and memory.

One of the usecase of RequestStore is to memoize value on per request basis. Currently, in this scenario while using RequestStore#fetch unused proc will be created multiple times


Benchmark:

2.4.3 :001 > require 'memory_profiler'
 => true
2.4.3 :002 > require 'request_store'
 => true
2.4.3 :003 > require 'benchmark/ips'
 => true
2.4.3 :004 >
2.4.3 :005 >   module RequestStore
2.4.3 :006?>     def self.fetch_without_proc_creation(key)
2.4.3 :007?>         # Suggested
2.4.3 :008 >           store[key] = yield unless exist?(key)
2.4.3 :009?>         store[key]
2.4.3 :010?>       end
2.4.3 :011?>     def self.fetch_with_proc_creation(key, &block)
2.4.3 :012?>         # current
2.4.3 :013 >           store[key] = yield unless exist?(key)
2.4.3 :014?>         store[key]
2.4.3 :015?>       end
2.4.3 :016?>   end ; nil
 => nil
2.4.3 :017 >
2.4.3 :018 >   Benchmark.ips do |x|
2.4.3 :019 >       x.config(:time => 5, :warmup => 2)
2.4.3 :020?>     x.report("with &block") { RequestStore.fetch_with_proc_creation(:a){0} }
2.4.3 :021?>
2.4.3 :022 >       x.report("without &block") {RequestStore.fetch_without_proc_creation(:b){1}}
2.4.3 :023?>
2.4.3 :024 >       x.compare!
2.4.3 :025?>   end ; nil
Warming up --------------------------------------
         with &block   101.397k i/100ms
      without &block   157.885k i/100ms
Calculating -------------------------------------
         with &block      1.474M (± 2.6%) i/s -      7.402M in   5.024766s
      without &block      2.554M (± 1.9%) i/s -     12.789M in   5.009695s

Comparison:
      without &block:  2553852.9 i/s
         with &block:  1474212.3 i/s - 1.73x  slower

 => nil
2.4.3 :026 >
2.4.3 :027 >   MemoryProfiler.report{ 100.times{ RequestStore.fetch_with_proc_creation(:aa){0} } }.pretty_print(detailed_report: false, allocated_strings: false, retained_strings: 0)
Total allocated: 8000 bytes (100 objects)
Total retained:  0 bytes (0 objects)

Allocated String Report
-----------------------------------

 => nil
2.4.3 :028 >
2.4.3 :029 >   MemoryProfiler.report{ 100.times{ RequestStore.fetch_without_proc_creation(:bb){1} } }.pretty_print(detailed_report: false, allocated_strings: false, retained_strings: 0)
Total allocated: 0 bytes (0 objects)
Total retained:  0 bytes (0 objects)

Allocated String Report
-----------------------------------

 => nil
2.4.3 :030 >
  • Loading branch information
Anmol Chopra committed Feb 28, 2018
1 parent 6a0f3c9 commit d23d5aa
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion lib/request_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def self.exist?(key)
store.key?(key)
end

def self.fetch(key, &block)
def self.fetch(key)
store[key] = yield unless exist?(key)
store[key]
end
Expand Down

0 comments on commit d23d5aa

Please sign in to comment.