From 68d00a9edd10b99c59b3ee78f62c1f8a9255db18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 13 May 2022 11:26:20 +0200 Subject: [PATCH 1/2] Improve `bundler/setup` performance again On a different patch, it was noticed Ngam Pham that we are calling `LazySpecification#hash` many times, and simply memoizing that led to a very considerable performance improvement in his app. I noticed though that we shouldn't be calling `LazySpecification#hash` that many times, and I located the culprit at `SpecSet#for` where we were deduplicating the partial aggregated result on every iteration. It is enough to do it just once at the end. This leads on a 12% speedup on Rails repository Gemfile vs the previous 8% I was getting from memoizing `LazySpecification#hash`. Also, after this patch memoizing `LazySpecification#hash` has no effect in performance anymore. Co-authored-by: Ngan Pham --- bundler/lib/bundler/spec_set.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bundler/lib/bundler/spec_set.rb b/bundler/lib/bundler/spec_set.rb index a19d18388ab8..dc55e5eaed34 100644 --- a/bundler/lib/bundler/spec_set.rb +++ b/bundler/lib/bundler/spec_set.rb @@ -24,7 +24,7 @@ def for(dependencies, check = false, match_current_platform = false) specs_for_dep = spec_for_dependency(dep, match_current_platform) if specs_for_dep.any? - match_current_platform ? specs += specs_for_dep : specs |= specs_for_dep + specs += specs_for_dep specs_for_dep.first.dependencies.each do |d| next if d.type == :development @@ -40,6 +40,8 @@ def for(dependencies, check = false, match_current_platform = false) specs << spec end + specs.uniq! unless match_current_platform + check ? true : specs end From 2ea2523afd684987b96c9cd747b3c7a9547da691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 13 May 2022 15:56:50 +0200 Subject: [PATCH 2/2] Use `Array#concat` in `SpecSet#for` to save memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On `rails/rails` repository Gemfile, running the following script ``` # script.rb require "bundler/setup" ``` #### Before ``` ➜ rails git:(main) ✗ BUNDLER_VERSION=2.4.0.dev ruby-memory-profiler --pretty --no-detailed --allocated-strings=0 --retained-strings=0 script.rb Total allocated: 24.37 MB (207937 objects) Total retained: 2.98 MB (34152 objects) ``` #### After ``` ➜ rails git:(main) ✗ BUNDLER_VERSION=2.4.0.dev ruby-memory-profiler --pretty --no-detailed --allocated-strings=0 --retained-strings=0 script.rb Total allocated: 22.27 MB (206856 objects) Total retained: 2.98 MB (34152 objects) ``` Co-authored-by: Josh Nichols --- bundler/lib/bundler/spec_set.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/lib/bundler/spec_set.rb b/bundler/lib/bundler/spec_set.rb index dc55e5eaed34..44715c356743 100644 --- a/bundler/lib/bundler/spec_set.rb +++ b/bundler/lib/bundler/spec_set.rb @@ -24,7 +24,7 @@ def for(dependencies, check = false, match_current_platform = false) specs_for_dep = spec_for_dependency(dep, match_current_platform) if specs_for_dep.any? - specs += specs_for_dep + specs.concat(specs_for_dep) specs_for_dep.first.dependencies.each do |d| next if d.type == :development