From 3bf93a2ff92c6ec7ddfd35125f674a67934829c4 Mon Sep 17 00:00:00 2001 From: Artur Petrov Date: Tue, 14 Mar 2023 22:51:11 +0300 Subject: [PATCH 1/3] Add quick benchmark --- activerecord/lib/active_record/relation.rb | 9 ++- .../active_record/relation/finder_methods.rb | 19 ++++- .../cases/associations/performance_test.rb | 76 +++++++++++++++++++ 3 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 activerecord/test/cases/associations/performance_test.rb diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index e2c188d3bc4df..e797418dbfd3d 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -838,7 +838,14 @@ def self.strict_loading_value def preload_associations(records) # :nodoc: preload = preload_values - preload += eager_loading? ? includes_values_non_referenced : includes_values + if ENV["SLIM_PATCH"].present? + preload += eager_loading? ? includes_values_non_referenced : includes_values + elsif ENV["SLIM_PATCH_CODE_ONLY"].present? + includes_values_non_referenced + preload += includes_values unless eager_loading? + else + preload += includes_values unless eager_loading? + end scope = strict_loading_value ? StrictLoadingScope : nil preload.each do |associations| ActiveRecord::Associations::Preloader.new(records: records, associations: associations, scope: scope).call diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 870342e6f755a..7851e176dc086 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -408,10 +408,21 @@ def construct_relation_for_exists(conditions) end def apply_join_dependency(eager_loading: group_values.empty?, full_eager_loading: false) - selected_includes_values = full_eager_loading ? includes_values : includes_values_referenced - join_dependency = construct_join_dependency( - eager_load_values | selected_includes_values, Arel::Nodes::OuterJoin - ) + if ENV["SLIM_PATCH"].present? + selected_includes_values = full_eager_loading ? includes_values : includes_values_referenced + join_dependency = construct_join_dependency( + eager_load_values | selected_includes_values, Arel::Nodes::OuterJoin + ) + elsif ENV["SLIM_PATCH_CODE_ONLY"].present? + selected_includes_values = full_eager_loading ? includes_values : includes_values_referenced + join_dependency = construct_join_dependency( + eager_load_values | includes_values, Arel::Nodes::OuterJoin + ) + else + join_dependency = construct_join_dependency( + eager_load_values | includes_values, Arel::Nodes::OuterJoin + ) + end relation = except(:includes, :eager_load, :preload).joins!(join_dependency) if eager_loading && has_limit_or_offset? && !( diff --git a/activerecord/test/cases/associations/performance_test.rb b/activerecord/test/cases/associations/performance_test.rb new file mode 100644 index 0000000000000..39d1054af1e45 --- /dev/null +++ b/activerecord/test/cases/associations/performance_test.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require "cases/helper" +require "cases/encryption/helper" +require "models/author" +require "models/book" +require "models/citation" +require "models/reader" +require "models/post" +require "models/reference" +require "models/comment" +require "models/rating" +require "models/category" +require "models/categorization" +require "models/tag" +require "models/tagging" +require "models/person" +require "models/club" +require "models/developer" +require "models/project" +require "models/computer" +require "models/company" +require "models/contract" +require "models/member" +require "models/membership" +require "models/sponsor" + +class AssociationsPerformanceTest < ActiveRecord::TestCase + include ActiveRecord::Encryption::PerformanceHelpers + + fixtures :authors, :books, :citations, :readers, :posts, :references, :comments, :ratings, + :categories, :categorizations, :tags, :taggings, :people, :clubs, :members, :memberships, + :sponsors, :developers, :projects, :developers_projects, :computers, :companies, :accounts + + DURATION = 10 + + def test_performance_tree_code_only + baseline = lambda do + ENV["SLIM_PATCH_CODE_ONLY"] = nil + ENV["SLIM_PATCH"] = nil + authors = Author.includes( + :books, { posts: :special_comments }, { categorizations: :category } + ).order("comments.body").where("posts.id = 4") + authors.to_a + end + + assert_slower_by_at_most 1.05, baseline: baseline, duration: DURATION do + ENV["SLIM_PATCH_CODE_ONLY"] = "true" + ENV["SLIM_PATCH"] = nil + authors = Author.includes( + :books, { posts: :special_comments }, { categorizations: :category } + ).order("comments.body").where("posts.id = 4") + authors.to_a + end + end + + def test_performance + baseline = lambda do + ENV["SLIM_PATCH_CODE_ONLY"] = nil + ENV["SLIM_PATCH"] = nil + authors = Author.includes( + :books, { posts: :special_comments }, { categorizations: :category } + ).order("comments.body").where("posts.id = 4") + authors.to_a + end + + assert_slower_by_at_most 1.2, baseline: baseline, duration: DURATION do + ENV["SLIM_PATCH_CODE_ONLY"] = nil + ENV["SLIM_PATCH"] = "true" + authors = Author.includes( + :books, { posts: :special_comments }, { categorizations: :category } + ).order("comments.body").where("posts.id = 4") + authors.to_a + end + end +end From 21a1cacd13fd8d98d90fe21217f5d0a6cd016592 Mon Sep 17 00:00:00 2001 From: Artur Petrov Date: Tue, 14 Mar 2023 23:17:56 +0300 Subject: [PATCH 2/3] Add honest test --- .../cases/associations/performance_test.rb | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/associations/performance_test.rb b/activerecord/test/cases/associations/performance_test.rb index 39d1054af1e45..c295093320c56 100644 --- a/activerecord/test/cases/associations/performance_test.rb +++ b/activerecord/test/cases/associations/performance_test.rb @@ -54,7 +54,7 @@ def test_performance_tree_code_only end end - def test_performance + def test_performance_objects_allocating baseline = lambda do ENV["SLIM_PATCH_CODE_ONLY"] = nil ENV["SLIM_PATCH"] = nil @@ -73,4 +73,24 @@ def test_performance authors.to_a end end + + def test_performance_sql_only + baseline = lambda do + ENV["SLIM_PATCH_CODE_ONLY"] = nil + ENV["SLIM_PATCH"] = nil + authors = Author.includes( + :books, { posts: :special_comments }, { categorizations: :category } + ).order("comments.body").where("posts.id = 4") + authors.to_sql + end + + assert_slower_by_at_most 0.8, baseline: baseline, duration: DURATION do + ENV["SLIM_PATCH_CODE_ONLY"] = nil + ENV["SLIM_PATCH"] = "true" + authors = Author.includes( + :books, { posts: :special_comments }, { categorizations: :category } + ).order("comments.body").where("posts.id = 4") + authors.to_sql + end + end end From b2b1a39ee7b86ce6b7b02b395f4b63b22b6f3454 Mon Sep 17 00:00:00 2001 From: Artur Petrov Date: Tue, 14 Mar 2023 23:18:51 +0300 Subject: [PATCH 3/3] Tune expected performance --- activerecord/test/cases/associations/performance_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/associations/performance_test.rb b/activerecord/test/cases/associations/performance_test.rb index c295093320c56..2b71effba583b 100644 --- a/activerecord/test/cases/associations/performance_test.rb +++ b/activerecord/test/cases/associations/performance_test.rb @@ -84,7 +84,7 @@ def test_performance_sql_only authors.to_sql end - assert_slower_by_at_most 0.8, baseline: baseline, duration: DURATION do + assert_slower_by_at_most 0.7, baseline: baseline, duration: DURATION do ENV["SLIM_PATCH_CODE_ONLY"] = nil ENV["SLIM_PATCH"] = "true" authors = Author.includes(