2013-03-03 5 views
8

Вот два простых блоков, которые делают то же самое:Почему .index быстрее, чем .all?

a = (0..100).to_a 

a.all? do |x| 
    !(x == 1000) 
end 

nil == a.index do |x| 
    x == 1000 
end 

За исключением, что второй один последовательно немного быстрее. Зачем?

         user  system  total  real 
testing all      1.140000 0.000000 1.140000 ( 1.144535) 
testing index     0.770000 0.000000 0.770000 ( 0.769195) 

ответ

5

Причина в том, что index - это метод Array. Ruby будет итерировать (в C) по элементам и привести их к блоку по очереди.

С другой стороны, all?, none?, one? (что все будет примерно на 30% медленнее), являются методы Enumerable. Они назовут each, что приведет к функции C, которая будет уступать блоку. Разница во времени связана с тем, что задействованы два yield с.

Обратите внимание, что специализированные версии all? и др. может быть определен на Array, и вы получите ту же производительность, что и index, но это было бы немного уродливым и избыточным ...

1

Это может быть из-за дополнительного шага ! делается в каждом повороте итерации с all?.

+0

Действительно? С этой логикой «x! = 1000» должно быть так же быстро? –

+1

@LeeJarvis При условии, что '! =' Определяется в C в соответствии с таким же алгоритмом, как '==', это должно быть предсказанием. – sawa

+2

Изменение его из '! (X == 1000)' на 'x! = 1000' не имеет существенного отличия. –