2010-02-18 4 views
63

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

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

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

ответ

76

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

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

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

13

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

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

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

+5

Время отливки для поплавков здесь не нужно. –

44

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

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

Печать:

0.000000 0.000000 0.000000 ( 0.501134) 
+1

Мне нравится идея использования встроенной библиотеки, но каковы первые три числа ('0,000000')? _Update: _ Посмотрел его [в документах] (http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html), и это время процессора пользователя, системное время процессора и сумма из этих двух. – lyonsinbeta

+1

Да. Они помечены, если вы используете «Benchmark.bm». Полезно видеть, где время тратится время от времени. Здесь вы можете видеть, что блок просто холост (0 всего, 0,5 реальных) –

+10

Или есть «Benchmark.realtime», который возвращает один понятный плавающий :) –

1

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

+1

или hitimes gem, который может иметь более высокую степень детализации в окнах, чем absolute_time ... – rogerdpack

0

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

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

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

diff = diff * 1000 
+2

'' '.to_i''' дает целое число и обрезает миллисекунды. Это будет работать, если вы просто изменили его на '' .to_f''' –

+1

Да, как говорит Райан; извинения за нисходящий голос, но на самом деле у него был один взлет, и я был вынужден его противодействовать. Умножение временной разницы _integer_ в секундах на 1000, чтобы получить миллисекунды? Да ладно, MARC.RS, конечно, вы просто троллировали нас! :-) –

+0

Нет, просто стараюсь изо всех сил –

0

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

date = Time.now.to_i 

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

0

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

Нет больше кода, как это:

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

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

benchmark :calculate_report # in class 

И просто вызовите ваш метод

user.calculate_report 
2

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

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

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

В 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 возвращает метку времени как поплавок с долей секунды. Возвращаемое фактическое число не имеет определенного значения (на которое вы должны положиться). Тем не менее, вы можете быть уверены, что следующий вызов вернет большее число, и, сравнив значения, вы можете получить разницу в реальном времени.

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