diff options
author | Yusuke Endoh <[email protected]> | 2020-09-11 12:00:29 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2020-09-28 14:54:22 +0900 |
commit | c55b5f106295aa3c7611a15a9bf7f0d589447ea7 (patch) | |
tree | c24603a4d9ee19f2f3e9f7792fbfce69872d119d /lib/rubygems/resolver/api_specification.rb | |
parent | 91865230cdebee3de7bfde1c91d4e3f63ad15787 (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/rubygems/resolver/api_specification.rb')
-rw-r--r-- | lib/rubygems/resolver/api_specification.rb | 21 |
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: |