[rubygems/rubygems] Improve efficiency of Index#use and #search_all
Rename Index#use(override = true) to #merge! Rename Index @all_specs to @duplicates, it is not actually all specs. @duplicates only holds specs that would have been overridden during a call to Index#use or Index#merge! Reduced dupes in @duplicates by not double adding the new spec to the index and the @duplicates during #merge! Reduce Array creation by using specialized methods when the one result or no results are needed from the search. https://github.com/rubygems/rubygems/commit/47e91125db
This commit is contained in:
parent
af1bedbbd9
commit
86b93f7481
@ -10,8 +10,8 @@ module Bundler
|
|||||||
i
|
i
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :specs, :all_specs, :sources
|
attr_reader :specs, :duplicates, :sources
|
||||||
protected :specs, :all_specs
|
protected :specs, :duplicates
|
||||||
|
|
||||||
RUBY = "ruby"
|
RUBY = "ruby"
|
||||||
NULL = "\0"
|
NULL = "\0"
|
||||||
@ -20,20 +20,20 @@ module Bundler
|
|||||||
@sources = []
|
@sources = []
|
||||||
@cache = {}
|
@cache = {}
|
||||||
@specs = Hash.new {|h, k| h[k] = {} }
|
@specs = Hash.new {|h, k| h[k] = {} }
|
||||||
@all_specs = Hash.new {|h, k| h[k] = EMPTY_SEARCH }
|
@duplicates = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_copy(o)
|
def initialize_copy(o)
|
||||||
@sources = o.sources.dup
|
@sources = o.sources.dup
|
||||||
@cache = {}
|
@cache = {}
|
||||||
@specs = Hash.new {|h, k| h[k] = {} }
|
@specs = Hash.new {|h, k| h[k] = {} }
|
||||||
@all_specs = Hash.new {|h, k| h[k] = EMPTY_SEARCH }
|
@duplicates = {}
|
||||||
|
|
||||||
o.specs.each do |name, hash|
|
o.specs.each do |name, hash|
|
||||||
@specs[name] = hash.dup
|
@specs[name] = hash.dup
|
||||||
end
|
end
|
||||||
o.all_specs.each do |name, array|
|
o.duplicates.each do |name, array|
|
||||||
@all_specs[name] = array.dup
|
@duplicates[name] = array.dup
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -47,7 +47,9 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def search_all(name)
|
def search_all(name)
|
||||||
all_matches = local_search(name) + @all_specs[name]
|
all_matches = specs_by_name(name) # always returns a new Array
|
||||||
|
dupes = @duplicates[name]
|
||||||
|
all_matches.concat(dupes) if dupes
|
||||||
@sources.each do |source|
|
@sources.each do |source|
|
||||||
all_matches.concat(source.search_all(name))
|
all_matches.concat(source.search_all(name))
|
||||||
end
|
end
|
||||||
@ -78,10 +80,11 @@ module Bundler
|
|||||||
|
|
||||||
alias_method :[], :search
|
alias_method :[], :search
|
||||||
|
|
||||||
def <<(spec)
|
def add(spec)
|
||||||
@specs[spec.name][spec.full_name] = spec
|
@specs[spec.name][spec.full_name] = spec
|
||||||
spec
|
spec
|
||||||
end
|
end
|
||||||
|
alias_method :<<, :add
|
||||||
|
|
||||||
def each(&blk)
|
def each(&blk)
|
||||||
return enum_for(:each) unless blk
|
return enum_for(:each) unless blk
|
||||||
@ -115,15 +118,25 @@ module Bundler
|
|||||||
names.uniq
|
names.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
def use(other, override_dupes = false)
|
# Combines indexes proritizing existing specs, like `Hash#reverse_merge!`
|
||||||
|
# Duplicate specs found in `other` are stored in `@duplicates`.
|
||||||
|
def use(other)
|
||||||
return unless other
|
return unless other
|
||||||
other.each do |s|
|
other.each do |spec|
|
||||||
if (dupes = search_by_spec(s)) && !dupes.empty?
|
exist?(spec) ? add_duplicate(spec) : add(spec)
|
||||||
# safe to << since it's a new array when it has contents
|
|
||||||
@all_specs[s.name] = dupes << s
|
|
||||||
next unless override_dupes
|
|
||||||
end
|
end
|
||||||
self << s
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
# Combines indexes proritizing specs from `other`, like `Hash#merge!`
|
||||||
|
# Duplicate specs found in `self` are saved in `@duplicates`.
|
||||||
|
def merge!(other)
|
||||||
|
return unless other
|
||||||
|
other.each do |spec|
|
||||||
|
if existing = find_by_spec(spec)
|
||||||
|
add_duplicate(existing)
|
||||||
|
end
|
||||||
|
add spec
|
||||||
end
|
end
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
@ -157,6 +170,10 @@ module Bundler
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def add_duplicate(spec)
|
||||||
|
(@duplicates[spec.name] ||= []) << spec
|
||||||
|
end
|
||||||
|
|
||||||
def specs_by_name_and_version(name, version)
|
def specs_by_name_and_version(name, version)
|
||||||
specs_by_name(name).select {|spec| spec.version == version }
|
specs_by_name(name).select {|spec| spec.version == version }
|
||||||
end
|
end
|
||||||
@ -168,8 +185,16 @@ module Bundler
|
|||||||
EMPTY_SEARCH = [].freeze
|
EMPTY_SEARCH = [].freeze
|
||||||
|
|
||||||
def search_by_spec(spec)
|
def search_by_spec(spec)
|
||||||
spec = @specs[spec.name][spec.full_name]
|
spec = find_by_spec(spec)
|
||||||
spec ? [spec] : EMPTY_SEARCH
|
spec ? [spec] : EMPTY_SEARCH
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_by_spec(spec)
|
||||||
|
@specs[spec.name][spec.full_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def exist?(spec)
|
||||||
|
@specs[spec.name].key?(spec.full_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -128,12 +128,12 @@ module Bundler
|
|||||||
def specs
|
def specs
|
||||||
@specs ||= begin
|
@specs ||= begin
|
||||||
# remote_specs usually generates a way larger Index than the other
|
# remote_specs usually generates a way larger Index than the other
|
||||||
# sources, and large_idx.use small_idx is way faster than
|
# sources, and large_idx.merge! small_idx is way faster than
|
||||||
# small_idx.use large_idx.
|
# small_idx.merge! large_idx.
|
||||||
idx = @allow_remote ? remote_specs.dup : Index.new
|
index = @allow_remote ? remote_specs.dup : Index.new
|
||||||
idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
|
index.merge!(cached_specs) if @allow_cached || @allow_remote
|
||||||
idx.use(installed_specs, :override_dupes) if @allow_local
|
index.merge!(installed_specs) if @allow_local
|
||||||
idx
|
index
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ module Bundler
|
|||||||
|
|
||||||
fetch_names(api_fetchers, unmet_dependency_names, remote_specs)
|
fetch_names(api_fetchers, unmet_dependency_names, remote_specs)
|
||||||
|
|
||||||
specs.use(remote_specs, false)
|
specs.use remote_specs
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependency_names_to_double_check
|
def dependency_names_to_double_check
|
||||||
|
Loading…
x
Reference in New Issue
Block a user