Как рассчитать время операции в рублях в миллисекундах? - PullRequest
73 голосов
/ 18 февраля 2010

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

Как ты это делаешь? В большинстве языков программирования это просто что-то вроде

start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start

Ответы [ 10 ]

81 голосов
/ 18 февраля 2010

Вы можете использовать класс Time Рубина. Например:

t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds

Теперь delta - это объект float, и вы можете получить столь же мелкий результат, как и класс.

54 голосов
/ 04 сентября 2012

Вы также можете использовать встроенную функцию Benchmark.measure:

require "benchmark"
puts(Benchmark.measure { sleep 0.5 })

Печать:

0.000000   0.000000   0.000000 (  0.501134)
16 голосов
/ 03 августа 2017

Использование Time.now (которое возвращает время настенных часов) в качестве базовых линий имеет несколько проблем, которые могут привести к неожиданному поведению. Это вызвано тем фактом, что время настенных часов подвержено изменениям, таким как добавленные високосные секунды или время поворота для настройки местного времени на эталонное время.

Если есть, например, дополнительная секунда, вставленная во время измерения, она будет отключена на секунду. Точно так же, в зависимости от условий локальной системы, вам, возможно, придется иметь дело с переходом на летнее время, с более быстрыми или медленными часами, или с часами, даже скачками во времени, что приводит к отрицательной продолжительности, и многими другими проблемами.

Решением этой проблемы является использование другого времени: монотонных часов. Этот тип часов обладает другими свойствами, чем настенные часы. Монитонически увеличивается, то есть никогда не возвращается назад и увеличивается с постоянной скоростью. При этом он не представляет настенные часы (то есть время, которое вы читаете из часов на вашей стене), но отметку времени, которую вы можете сравнить с более поздней отметкой времени, чтобы получить разницу.

В Ruby вы можете использовать такую ​​временную метку с Process.clock_gettime(Process::CLOCK_MONOTONIC), например:

t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63988.576809828

sleep 1.5 # do some work

t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63990.08359163

delta = t2 - t1
# => 1.5067818019961123
delta_in_milliseconds = delta * 1000
# => 1506.7818019961123

Метод Process.clock_gettime возвращает метку времени с плавающей запятой с долями секунды. Фактическое возвращаемое число не имеет определенного значения (на которое вы должны полагаться). Однако вы можете быть уверены, что следующий вызов вернет большее число, и, сравнив значения, вы получите разницу в реальном времени.

Эти атрибуты делают метод главным кандидатом для измерения разницы во времени, не видя сбоя вашей программы в самое неподходящее время (например, в полночь в канун Нового года, когда вставляется еще одна секунда).

Используемая здесь константа Process::CLOCK_MONOTONIC доступна во всех современных системах Linux, BSD и macOS, а также в подсистеме Linux для Windows. Он (насколько мне известно) пока недоступен для «сырых» систем Windows. Там вы можете использовать системный вызов GetTickCount вместо Process.clock_gettime, который также возвращает значение таймера с точностью до миллисекунды в Windows.

13 голосов
/ 18 февраля 2010

Вам следует взглянуть на модуль тестов, чтобы выполнить тесты.Однако в качестве быстрого и грязного метода синхронизации вы можете использовать что-то вроде этого:

def time
  now = Time.now.to_f
  yield
  endd = Time.now.to_f
  endd - now
end

Обратите внимание на использование Time.now.to_f, которое, в отличие от to_i, не будет усекаться до секунд.

1 голос
/ 19 марта 2019

Также мы можем создать простую функцию для записи любого блока кода:

def log_time
  start_at = Time.now

  yield if block_given?

  execution_time = (Time.now - start_at).round(2)
  puts "Execution time: #{execution_time}s"
end

log_time { sleep(2.545) } # Execution time: 2.55s
1 голос
/ 08 апреля 2013

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

1 голос
/ 18 февраля 2010

Использовать Time.now.to_f

0 голосов
/ 13 октября 2015

У меня есть гем, который может профилировать ваш метод ruby ​​(экземпляр или класс) - https://github.com/igorkasyanchuk/benchmark_methods.

Код больше не похож на этот:

t = Time.now
user.calculate_report
puts Time.now - t

Теперь вы можете сделать:

benchmark :calculate_report # in class

И просто назовите свой метод

user.calculate_report
0 голосов
/ 10 марта 2014

Если вы используете

date = Time.now.to_i

Вы получаете время в секундах, что далеко не точно, особенно если вы рассчитываете небольшие фрагменты кода.

0 голосов
/ 21 февраля 2014

Использование Time.now.to_i возвращает секунду, пройденную с 1970/01/01.Зная это, вы можете сделать

date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1

С этим у вас будет разница в секунду величина.Если вы хотите это за миллисекунды , просто добавьте к коду

diff = diff * 1000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...