-
Notifications
You must be signed in to change notification settings - Fork 99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Faster2: Cache the method, ivar, and arity and the ancestry memoized methods #38
Conversation
We can limit calls to memoized_ivar_for/unmemoized_method_for and related methods for things we've already calculated initially on the memoize :some_method call. Fixes prime_cache not priming inherited memoized methods, broken by matthewrudy#36 Fixes (un)memoize_all not clearing/priming subclass identifiers flush_cache now: 121143.3 i/s flush_cache PR 34: 16079.4 i/s - 7.53x slower flush_cache master: 3718.0 i/s - 32.58x slower flush_cache with args now: 43484.0 i/s flush_cache with args PR 34: 17488.5 i/s - 2.49x slower flush_cache with args master: 17279.3 i/s - 2.52x slower prime_cache now: 55946.9 i/s prime_cache PR 34: 12665.0 i/s - 4.42x slower prime_cache master: 6057.2 i/s - 9.24x slower prime_cache with args now: 30015.3 i/s prime_cache with args PR 34: 14012.1 i/s - 2.14x slower prime_cache with args master: 13914.9 i/s - 2.16x slower For a class with 40 memoized methods, total allocations is also greatly reduced where each method below is called 1,000 times: method | PR 34 | master | now ------ | ----- | ----- | --- prime_cache with args | 363421 | 164000 | 45004 prime_cache no args | 630535 | 168000 | 41000 flush_cache with args | 643361 | 164000 | 5000 flush_cache no args | 907607 | 168000 | 1000 SCRIPT: ```ruby def log_all_allocations(key = :line) require 'allocation_tracer' trace_keys = %i{path type class} if [:path, :file].include?(key) trace_keys = %i{line path type class} if key == :line ObjectSpace::AllocationTracer.setup(trace_keys) return_from_yield = nil result = ObjectSpace::AllocationTracer.trace do return_from_yield = yield nil end puts "Total: #{result.values.inject(0) { |count, v| count += v[0]}}" return_from_yield end require './lib/memoist' require 'set' $methods = Set.new class Person extend Memoist 1.upto(20) do |n| method = define_method("test_#{n}".to_sym) {} memoize(method) $methods.add(method) end 1.upto(20) do |n| method = define_method("test_#{n}?".to_sym) {} memoize(method) $methods.add(method) end end puts "prime_cache with args" p = Person.new log_all_allocations(:line) do 1_000.times do p.prime_cache(*$methods) end end puts "prime_cache no args" p = Person.new log_all_allocations(:line) do 1_000.times do p.prime_cache end end puts "flush_cache with args" p = Person.new log_all_allocations(:line) do 1_000.times do p.flush_cache(*$methods) end end puts "flush_cache no args" p = Person.new log_all_allocations(:line) do 1_000.times do p.flush_cache end end ```
@matthewrudy I know this makes things more complicated but at the same time, the |
@jrafanie i should never have added that identifier option, really |
But the tests pass, and you seem to be making good progress with the object count. So let's merge it. |
Faster2: Cache the method, ivar, and arity and the ancestry memoized methods
Thanks @matthewrudy, I agree, the identifier feature makes things harder. |
We can limit calls to memoized_ivar_for/unmemoized_method_for and
related methods for things we've already calculated initially on the
memoize :some_method call.
Fixes prime_cache not priming inherited memoized methods, broken by #36
Fixes (un)memoize_all not clearing/priming subclass identifiers
For a class with 40 memoized methods, total allocations is also
greatly reduced where each method below is called 1,000 times: