Skip to content
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

Reduce recorder memory usage #1479

Merged
merged 3 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions benchmarks/allocations/lambda_vs_block_with_select.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
require 'memory_profiler'

n = 10_000

def find_with_proc(argument)
lambda do |lambda_arg|
lambda_arg == argument
end
end

def find(argument, lambda_arg)
lambda_arg == argument
end

puts "#{n} items - ruby #{RUBY_VERSION}"

puts
puts "find_with_proc"

MemoryProfiler.report do
100.times do
1.upto(n).select(&find_with_proc(50))
end
end.pretty_print

puts
puts "find"

MemoryProfiler.report do
100.times do
1.upto(n).select { |i| find(50, i) }
end
end.pretty_print

# $ ruby benchmarks/allocations/2_lambda_ref_find.rb
# 10000 items - ruby 3.2.2
#
# find_with_proc
# Total allocated: 29600 bytes (400 objects)
# Total retained: 0 bytes (0 objects)
#
# allocated memory by gem
# -----------------------------------
# 29600 other
#
# allocated memory by file
# -----------------------------------
# 29600 benchmarks/allocations/2_lambda_ref_find.rb
#
# allocated memory by location
# -----------------------------------
# 21600 benchmarks/allocations/2_lambda_ref_find.rb:22
# 8000 benchmarks/allocations/2_lambda_ref_find.rb:6
#
# allocated memory by class
# -----------------------------------
# 13600 Enumerator
# 8000 Array
# 8000 Proc
#
# allocated objects by gem
# -----------------------------------
# 400 other
#
# allocated objects by file
# -----------------------------------
# 400 benchmarks/allocations/2_lambda_ref_find.rb
#
# allocated objects by location
# -----------------------------------
# 300 benchmarks/allocations/2_lambda_ref_find.rb:22
# 100 benchmarks/allocations/2_lambda_ref_find.rb:6
#
# allocated objects by class
# -----------------------------------
# 200 Array
# 100 Enumerator
# 100 Proc
#
#
# find
# Total allocated: 21600 bytes (300 objects)
# Total retained: 0 bytes (0 objects)
#
# allocated memory by gem
# -----------------------------------
# 21600 other
#
# allocated memory by file
# -----------------------------------
# 21600 benchmarks/allocations/2_lambda_ref_find.rb
#
# allocated memory by location
# -----------------------------------
# 21600 benchmarks/allocations/2_lambda_ref_find.rb:31
#
# allocated memory by class
# -----------------------------------
# 13600 Enumerator
# 8000 Array
#
# allocated objects by gem
# -----------------------------------
# 300 other
#
# allocated objects by file
# -----------------------------------
# 300 benchmarks/allocations/2_lambda_ref_find.rb
#
# allocated objects by location
# -----------------------------------
# 300 benchmarks/allocations/2_lambda_ref_find.rb:31
#
# allocated objects by class
# -----------------------------------
# 200 Array
# 100 Enumerator
20 changes: 11 additions & 9 deletions lib/rspec/mocks/any_instance/recorder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,23 @@ def stop_observing!(method_name)

private

def ancestor_is_an_observer?(method_name)
lambda do |ancestor|
unless ancestor == @klass
::RSpec::Mocks.space.
any_instance_recorder_for(ancestor).already_observing?(method_name)
end
end
def ancestor_is_an_observer?(ancestor, method_name)
return if ancestor == @klass

::RSpec::Mocks.space.
any_instance_recorder_for(ancestor).already_observing?(method_name)
end

def super_class_observers_for(method_name)
@klass.ancestors.select(&ancestor_is_an_observer?(method_name))
@klass.ancestors.select do |ancestor|
ancestor_is_an_observer?(ancestor, method_name)
end
end

def super_class_observing?(method_name)
@klass.ancestors.any?(&ancestor_is_an_observer?(method_name))
@klass.ancestors.any? do |ancestor|
ancestor_is_an_observer?(ancestor, method_name)
end
end

def normalize_chain(*args)
Expand Down
Loading