Подтвердить что ты не робот

Почему array.min так медленно?

Я заметил, что array.min кажется медленным, поэтому я сделал этот тест против своей наивной реализации:

require 'benchmark'
array = (1..100000).to_a.shuffle

Benchmark.bmbm(5) do |x|
  x.report("lib:") { 99.times { min = array.min } }
  x.report("own:") { 99.times { min = array[0]; array.each { |n| min = n if n < min } } }
end

Результаты:

Rehearsal -----------------------------------------
lib:    1.531000   0.000000   1.531000 (  1.538159)
own:    1.094000   0.016000   1.110000 (  1.102130)
-------------------------------- total: 2.641000sec

            user     system      total        real
lib:    1.500000   0.000000   1.500000 (  1.515249)
own:    1.125000   0.000000   1.125000 (  1.145894)

Я в шоке. Как может моя собственная реализация запустить блок через each избили встроенный? И избили его так много?

Как я ошибаюсь? Или это как-то нормально? Я в замешательстве.


Моя версия Ruby, работающая под Windows 8.1 Pro:

C:\>ruby --version
ruby 2.2.3p173 (2015-08-18 revision 51636) [i386-mingw32]
4b9b3361

Ответ 1

Посмотрите на реализацию Enumerable # min. Он мог бы использовать each в конечном итоге для циклического прохождения элементов и получения элемента min, но до этого он выполняет некоторую дополнительную проверку, чтобы увидеть, нужно ли ему возвращать несколько элементов или если нужно сравнить элементы через переданный блок, В вашем случае элементы будут сравниваться с помощью min_i, и я подозреваю, что там, где происходит разница в скорости - эта функция будет медленнее, чем просто сравнивая два числа.

Нет дополнительной оптимизации для массивов, все перечислимые объекты пройдены одинаково.

Ответ 2

Это даже быстрее, если вы используете:

def my_min(ary)
  the_min = ary[0]
  i = 1
  len = ary.length
  while i < len
    the_min = ary[i] if ary[i] < the_min
    i += 1
  end
  the_min
end

Примечание

Я знаю, что это не ответ, но я подумал, что стоит поделиться и поставить этот код в комментарий было бы чрезвычайно уродливо.