Feature #4917
Updated by sawa (Tsuyoshi Sawada) about 4 years ago
`Kernel#Array`, As a performance improvement in certain cases, nil should respond to to_ary. Kernel#Array, when passed `nil`, nil, first tries to send `to_ary`, which to_ary to nil (which actually ends up calling `method_missing`, method_missing on nil) and then tries to send `to_a`, to_a to nil which finally succeeds. When `Kernel#Array` Kernel#Array is used frequently, often, for example in library/gem code, this can have a noticeable, if relatively small, negative impact on the overall application performance. For performance improvement, `nil` should respond to `to_ary`. I propose: ```ruby NilClass.class_eval { alias to_ary to_a } ``` Using the following code, ```ruby $ irb > RUBY_VERSION => "1.9.2" > require 'benchmark' > def bench(times) Benchmark.bmbm{|x| x.report{times.times(&Proc.new)}} end # Sees Let's zero the scale.... > bench(10_000_000) { } # The "before" benchmark.... > bench(10_000_000) { Array(nil) } # An optimization.... > NilClass.class_eval { alias to_ary to_a } # The "after" benchmark.... > bench(10_000_000) { Array(nil) } # Much faster! # Let's see how many times method_missing is called actually gets called.... > NilClass.class_eval { undef to_ary } > class NilClass > alias method_missing_without_hit method_missing > def method_missing(name, *args, &block) > $method_missing_hits += 1 > method_missing_without_hit(name, *args, &block) > end > end ``` I measured the benchmark and `method_missing` calls. ```ruby NilClass.class_eval { undef to_ary } > $method_missing_hits = 0 > bench(100_000) { Array(nil) } # Very slow! > $method_missing_hits # => 200005 ``` ```ruby > NilClass.class_eval { alias to_ary to_a } > $method_missing_hits = 0 > bench(100_000) { Array(nil) } # Instantaneous! > $method_missing_hits # => 0 ``` It is observed that the former is very slow. The latter is instantaneous.