ruby-changes:63163
From: Yusuke <ko1@a...>
Date: Mon, 28 Sep 2020 14:54:50 +0900 (JST)
Subject: [ruby-changes:63163] c55b5f1062 (master): [rubygems/rubygems] Avoid duplicated generation of APISpecification objects
https://git.ruby-lang.org/ruby.git/commit/?id=c55b5f1062 From c55b5f106295aa3c7611a15a9bf7f0d589447ea7 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh <mame@r...> Date: Fri, 11 Sep 2020 12:00:29 +0900 Subject: [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 diff --git a/lib/rubygems/resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb index a47d910..232c2b0 100644 --- a/lib/rubygems/resolver/api_specification.rb +++ b/lib/rubygems/resolver/api_specification.rb @@ -7,6 +7,17 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/api_specification.rb#L7 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 https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/api_specification.rb#L29 @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: -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/