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

Мера и контрольное время для методов Ruby

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

def foo
# code to access database
# code to access redis. 
end
4b9b3361

Ответ 1

Вы можете использовать объект Time. (Документы времени)

Например,

start = Time.now
# code to time
finish = Time.now

diff = finish - start

diff будет в секундах, как число с плавающей запятой.

EDIT: end зарезервировано.

Ответ 2

Самый простой способ:

require 'benchmark'

def foo
 time = Benchmark.measure {
  code to test
 }
 puts time.real #or save it to logs
end

Пример вывода:

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

Значения: cpu time, системное время, общее и реальное прошедшее время.

Источник: ruby ​​docs.

Ответ 3

Использовать сравнительный отчет

require 'benchmark' # Might be necessary.

def foo
  Benchmark.bm(20) do |bm|  # The 20 is the width of the first column in the output.
    bm.report("Access Database:") do 
      # Code to access database.
    end

    bm.report("Access Redis:") do
      # Code to access redis.
    end
  end
end

Это выведет что-то вроде следующего:

                        user     system      total        real
Access Database:    0.020000   0.000000   0.020000 (  0.475375)
Access Redis:       0.000000   0.000000   0.000000 (  0.000037)

<------ 20 ------->  # This is where the 20 comes in. NOTE: Not shown in output.

Более подробную информацию можно найти здесь here.

Ответ 4

Во-вторых, определение функции measure() с помощью аргумента блока кода Ruby может помочь упростить код меры времени:

def measure(&block)
  start = Time.now
  block.call
  Time.now - start
end

# t1 and t2 is the executing time for the code blocks.
t1 = measure { sleep(1) }

t2 = measure do
  sleep(2)
end

Ответ 5

Многие из ответов предполагают использование Time.now. Но стоит знать, что Time.now может измениться. Системные часы могут дрейфовать и могут быть исправлены системным администратором или через NTP. Поэтому Time.now может прыгнуть вперед или назад и дать неточные результаты.

Лучшее решение - использовать монотонные часы операционной системы, которые всегда движутся вперед. Ruby 2.1 и выше дают доступ к этому через:

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# code to time
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
diff = finish - start # gets time is seconds as a float

Вы можете прочитать подробности здесь. Также вы можете увидеть популярный проект Ruby, Sidekiq, который переключился на монотонные часы.

Ответ 6

Посмотрите в пакет ruby-prof, он должен иметь то, что вам нужно. Это создаст огромные стеки вызовов с таймингами.

http://ruby-prof.rubyforge.org/

Это может быть слишком зернистым, и в этом случае просто обернуть большие разделы в Benchmark.measure может быть хорошим способом.

Ответ 7

В духе wquist answer, но немного проще, вы также можете сделать это, как показано ниже:

start = Time.now
# code to time
Time.now - start