From def144807684e69871cba63c29c41a8fd7aa1a2e Mon Sep 17 00:00:00 2001 From: Joel Hawksley Date: Wed, 25 Sep 2024 15:48:23 -0600 Subject: [PATCH] Add basic internal testing for memory allocations (#2097) * Add basic internal testing for memory allocations * add RUBY_VERSION to debug output * fix allocation counts * fix allocation counts * use compile cache helper * try using cache clearing * try using more specific ruby version targets and ensure compilation * add allocation counts for CI ruby versions * use counts from CI * move require to top of file * try removing component from compile cache to stabilize allocations * another stabilization attempt --- Gemfile.lock | 2 ++ docs/CHANGELOG.md | 4 +++ test/sandbox/test/rendering_test.rb | 53 ++++++++++++++++------------- test/test_helper.rb | 9 +++++ view_component.gemspec | 1 + 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 17de0de18..8538fa741 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,6 +76,7 @@ GEM tzinfo (~> 2.0) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) + allocation_stats (0.1.5) ansi (1.5.0) appraisal (2.5.0) bundler @@ -330,6 +331,7 @@ PLATFORMS ruby DEPENDENCIES + allocation_stats (~> 0.1.5) appraisal (~> 2.4) benchmark-ips (~> 2.13.0) better_html diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index b3c577e5d..9d44e5454 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,10 @@ nav_order: 5 ## main +* Add basic internal testing for memory allocations. + + *Joel Hawksley* + * Add support for request formats. *Joel Hawksley* diff --git a/test/sandbox/test/rendering_test.rb b/test/sandbox/test/rendering_test.rb index 6f8e66b51..afd4e1ca7 100644 --- a/test/sandbox/test/rendering_test.rb +++ b/test/sandbox/test/rendering_test.rb @@ -9,6 +9,19 @@ def test_render_inline assert_selector("div", text: "hello,world!") end + def test_render_inline_allocations + # Stabilize compilation status ahead of testing allocations to simulate rendering + # performance with compiled component + ViewComponent::CompileCache.cache.delete(MyComponent) + MyComponent.ensure_compiled + + assert_allocations("3.4.0" => 107, "3.3.5" => 116, "3.3.0" => 129, "3.2.5" => 115, "3.1.6" => 115, "3.0.7" => 125) do + render_inline(MyComponent.new) + end + + assert_selector("div", text: "hello,world!") + end + def test_render_in_view_context render_in_view_context { render(MyComponent.new) } @@ -717,34 +730,28 @@ def test_collection_component_present_custom_parameter_name_with_activemodel end def test_component_with_invalid_parameter_names - old_cache = ViewComponent::CompileCache.cache - ViewComponent::CompileCache.cache = Set.new - - exception = - assert_raises ViewComponent::ReservedParameterError do - InvalidParametersComponent.compile(raise_errors: true) - end + with_new_cache do + exception = + assert_raises ViewComponent::ReservedParameterError do + InvalidParametersComponent.compile(raise_errors: true) + end - assert_match(/InvalidParametersComponent initializer can't accept the parameter/, exception.message) - ensure - ViewComponent::CompileCache.cache = old_cache + assert_match(/InvalidParametersComponent initializer can't accept the parameter/, exception.message) + end end def test_component_with_invalid_named_parameter_names - old_cache = ViewComponent::CompileCache.cache - ViewComponent::CompileCache.cache = Set.new - - exception = - assert_raises ViewComponent::ReservedParameterError do - InvalidNamedParametersComponent.compile(raise_errors: true) - end + with_new_cache do + exception = + assert_raises ViewComponent::ReservedParameterError do + InvalidNamedParametersComponent.compile(raise_errors: true) + end - assert_match( - /InvalidNamedParametersComponent initializer can't accept the parameter `content`/, - exception.message - ) - ensure - ViewComponent::CompileCache.cache = old_cache + assert_match( + /InvalidNamedParametersComponent initializer can't accept the parameter `content`/, + exception.message + ) + end end def test_collection_component_with_trailing_comma_attr_reader diff --git a/test/test_helper.rb b/test/test_helper.rb index 1e6d449bb..61e9ff33e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "allocation_stats" require "simplecov" require "simplecov-console" require "rails/version" @@ -187,3 +188,11 @@ def capture_warnings(&block) end end end + +def assert_allocations(count_map, &block) + trace = AllocationStats.trace(&block) + total = trace.allocations.all.size + count = count_map[RUBY_VERSION] + + assert_equal count, total, "Expected #{count} allocations, got #{total} allocations for Ruby #{RUBY_VERSION}" +end diff --git a/view_component.gemspec b/view_component.gemspec index 3a6f3dacb..03fc32c77 100644 --- a/view_component.gemspec +++ b/view_component.gemspec @@ -32,6 +32,7 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency "activesupport", [">= 5.2.0", "< 8.0"] spec.add_runtime_dependency "method_source", "~> 1.0" spec.add_runtime_dependency "concurrent-ruby", "~> 1.0" + spec.add_development_dependency "allocation_stats", "~> 0.1.5" spec.add_development_dependency "appraisal", "~> 2.4" spec.add_development_dependency "benchmark-ips", "~> 2.13.0" spec.add_development_dependency "better_html"