2015-03-10 3 views
3

Как определить, какой метод работает быстрее? Имея трудное время, читая о Benchmark в документах Ruby и фактически реализуя его. БлагодарностиКак узнать, какой метод работает быстрее

def count_between(list_of_integers, lower_bound, upper_bound) 
    count = 0 
    list_of_integers.each do |x| 
    (x >= lower_bound && x <= upper_bound) ? count += 1 : next 
    end 
    count 
end 

или

def count_between(list_of_integers, lower_bound, upper_bound) 
count = 0 
list_of_integers.each do |x| 
    count += 1 if x.between?(lower_bound, upper_bound) 
end 
count 
end 
+0

Модуль ['Benchmark'] (http://ruby-doc.org/stdlib-2.1.0/libdoc/benchmark/rdoc/Benchmark.html) не так уж прост в использовании. Что вы не понимаете в этом? – zwippie

+0

Проверьте наличие [Gprof] (https://en.wikipedia.org/wiki/Gprof). – kenorb

ответ

1
require 'benchmark' 

def count_between_1(list_of_integers, lower_bound, upper_bound) 
    count = 0 
    list_of_integers.each do |x| 
    (x >= lower_bound && x <= upper_bound) ? count += 1 : next 
    end 
    count 
end 

def count_between_2(list_of_integers, lower_bound, upper_bound) 
    count = 0 
    list_of_integers.each do |x| 
    count += 1 if x.between?(lower_bound, upper_bound) 
    end 
    count 
end 

list_of_integers = (1..100_000).to_a 
lower_bound = 5 
upper_bound = 80_000 

Benchmark.bm do |x| 
    x.report do 
    count_between_1(list_of_integers, lower_bound, upper_bound) 
    end 

    x.report do 
    count_between_2(list_of_integers, lower_bound, upper_bound) 
    end 
end 

И результаты:

 user  system  total  real 
0.010000 0.000000 0.010000 ( 0.008910) 
0.010000 0.000000 0.010000 ( 0.018098) 

Так что первый вариант намного быстрее.

+0

Спасибо вам за ваши ответы. Хотите начать выполнение этих тестов по мере того, как я больше разбираюсь в рефакторинге. – Jgoo83

1

Здесь.

def count_between(list_of_integers, lower_bound, upper_bound) 
    count = 0 
    s = Benchmark.realtime do 
     list_of_integers.each do |x| 
      count += 1 if x.between?(lower_bound, upper_bound) 
     end 
    end 
    puts "Method took #{"%.04f" % s} seconds to complete" 
    count 
end 

Benchmark.realtime будет время блок, который он окружает, и возвращает число с плавающей точкой, которое указывает количество секунд, которое потребовалось, чтобы exeucte блок кода (в пределах точности чисел с плавающей точкой и точность системы Часы).

Другие методы, такие как Benchmark.report и Benchmark.measure, дадут разбивку пользовательского, системного и реального времени выполнения, которые полезны для отладки, почему часть кода медленнее, чем ожидалось.

5

Проблема с эталоном заключается в том, что для чего-то, что выполняется очень быстро, вам нужно выполнить тест несколько раз, чтобы быть уверенным в результате. Benchmark не дает вам никакой помощи в этом - вы получаете петли внутри своих блоков report и перебираете счетчики, которые повторяются.

Ценник эталон-ips делает некоторые из них для вас. Основное использование в значительной степени совпадает с версией STDLIB:

require 'benchmark/ips' 

#define your methods and test data here. 
Benchmark.ips do |x| 
    x.report 'count between 1' do 
    count_between_1(list_of_integers, lower_bound, upper_bound) 
    end 

    x.report 'count between 2' do 
    count_between_2(list_of_integers, lower_bound, upper_bound) 
    end 
end 

Производит вывод, как

count between 1 143.377 (± 4.9%) i/s - 728.000 
count between 2  64.489 (± 4.7%) i/s - 324.000 

что делает его немного легче увидеть, является ли результат значит или нет.

Смежные вопросы