rubygems/rubygems — pull request #842 by tenderlove (2014-03-05 23:28:33+00:00)
Title: only loop over spec dependencies to resolve conflicts

Before this commit, the `conflicts` method would loop over every
activated gem and the `conflicts` method would get slower as you
activate more gems.

This commit speeds up the `conflicts` method which is called on ever gem
activation by only looping over dependencies on the spec itself, then
looking up possible conflicts from the loaded_specs hash.

Here is the benchmark:

```ruby
def util_spec name, version = 2
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = name
s.version = version
s.author = 'A User'
s.email = 'example@example.com'
s.homepage = 'http://example.com'
s.summary = "this is a summary"
s.description = "This is a test description"
end

spec.loaded_from = spec.spec_file

Gem::Specification.add_spec spec

return spec
end

require 'benchmark/ips'

(ENV['N'] || 100).to_i.times { |i| util_spec(i.to_s).activate }

p Gem.loaded_specs.size

Benchmark.ips do |x|
spec = util_spec 'a'
# Typical mode, runs the block as many times as it can
x.report("conflicts") { spec.conflicts }
end
```

Before my change:

```
[aaron@higgins rubygems (master)]$ N=100 ruby -I lib test.rb
101
Calculating -------------------------------------
conflicts 1957 i/100ms
-------------------------------------------------
conflicts 20090.1 (±4.6%) i/s - 101764 in 5.077002s
[aaron@higgins rubygems (master)]$ N=1000 ruby -I lib test.rb
1001
Calculating -------------------------------------
conflicts 214 i/100ms
-------------------------------------------------
conflicts 2209.6 (±5.0%) i/s - 11128 in 5.050977s
```

After my change:

```
[aaron@higgins rubygems (master)]$ N=100 ruby -I lib test.rb
101
Calculating -------------------------------------
conflicts 71357 i/100ms
-------------------------------------------------
conflicts 2230414.4 (±7.2%) i/s - 11131692 in 5.022458s
[aaron@higgins rubygems (master)]$ N=1000 ruby -I lib test.rb
1001
Calculating -------------------------------------
conflicts 69479 i/100ms
-------------------------------------------------
conflicts 2171237.1 (±6.2%) i/s - 10838724 in 5.013410s
```

You can see that after this change the speed of `conflicts` stays about
the same regardless of the number of specs loaded.