ruby/ruby — pull request #671 by csfrancis (2014-07-18 00:20:52+00:00)
Title: Optimize any? object allocations for Array and Hash

This optimizes `Enumerable#any?` to eliminate unneeded object allocations when an Array or Hash is empty.

This preserves the semantics of `any?`:
> If the block is not given, Ruby adds an implicit block of { |obj| obj } that will cause any? to return true if at least one of the collection members is not false or nil.

If the array or hash is empty and `each` has not been overridden, this allows `any?` to return immediately without calling `rb_block_call`.

Here's the results of a benchmark I ran:
```
ruby 2.1.2
user system total real
empty array 1.710000 0.010000 1.720000 ( 1.719641)
empty hash 1.820000 0.000000 1.820000 ( 1.825466)
non-empty array 3.320000 0.000000 3.320000 ( 3.335912)
non-empty hash 6.420000 0.030000 6.450000 ( 6.462176)
```
```
ruby 2.1.2 with any? optimization
user system total real
empty array 0.940000 0.000000 0.940000 ( 0.936230)
empty hash 0.870000 0.000000 0.870000 ( 0.869757)
non-empty array 3.110000 0.000000 3.110000 ( 3.115228)
non-empty hash 6.840000 0.010000 6.850000 ( 6.868313)
```
And here's the benchmark code:
```ruby
require 'benchmark'

iters = (1..10_000_000)
Benchmark.bm(16) do |x|
x.report("empty array") { iters.each { [].any? } }
x.report("empty hash") { iters.each { {}.any? } }
x.report("non-empty array") { iters.each { [1].any? } }
x.report("non-empty hash") { iters.each { { :foo => true }.any? } }
end
```