summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYusuke Endoh <mame@ruby-lang.org>2020-09-11 12:00:29 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2020-09-28 14:54:22 +0900
commitc55b5f106295aa3c7611a15a9bf7f0d589447ea7 (patch)
treec24603a4d9ee19f2f3e9f7792fbfce69872d119d /lib
parent91865230cdebee3de7bfde1c91d4e3f63ad15787 (diff)
[rubygems/rubygems] Avoid duplicated generation of APISpecification objects
As far as I could see, `Gem::Resolver::APISpecification` objects are supposed to be immutable. If my guessing is correct, then we can cache and reuse its instances for performance. At least, `rake` passes on my machine. Before this change: ``` $ time ruby -I lib bin/gem install --no-doc aws-sdk Successfully installed aws-sdk-3.0.1 1 gem installed real 0m37.104s user 0m36.952s sys 0m0.333s ``` After this change: ``` $ time ruby -I lib bin/gem install --no-doc aws-sdk Successfully installed aws-sdk-3.0.1 1 gem installed real 0m23.905s user 0m23.740s sys 0m0.365s ``` https://github.com/rubygems/rubygems/commit/7e8fbba85c
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3599
Diffstat (limited to 'lib')
-rw-r--r--lib/rubygems/resolver/api_specification.rb21
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/rubygems/resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb
index a47d910331..232c2b041b 100644
--- a/lib/rubygems/resolver/api_specification.rb
+++ b/lib/rubygems/resolver/api_specification.rb
@@ -7,6 +7,17 @@
class Gem::Resolver::APISpecification < Gem::Resolver::Specification
##
+ # We assume that all instances of this class are immutable;
+ # so avoid duplicated generation for performance.
+ @@cache = {}
+ def self.new(set, api_data)
+ cache_key = [set, api_data]
+ cache = @@cache[cache_key]
+ return cache if cache
+ @@cache[cache_key] = super
+ end
+
+ ##
# Creates an APISpecification for the given +set+ from the rubygems.org
# +api_data+.
#
@@ -18,12 +29,12 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
@set = set
@name = api_data[:name]
- @version = Gem::Version.new api_data[:number]
- @platform = Gem::Platform.new api_data[:platform]
- @original_platform = api_data[:platform]
+ @version = Gem::Version.new(api_data[:number]).freeze
+ @platform = Gem::Platform.new(api_data[:platform]).freeze
+ @original_platform = api_data[:platform].freeze
@dependencies = api_data[:dependencies].map do |name, ver|
- Gem::Dependency.new name, ver.split(/\s*,\s*/)
- end
+ Gem::Dependency.new(name, ver.split(/\s*,\s*/)).freeze
+ end.freeze
end
def ==(other) # :nodoc: