2010-02-18 6 views
63

Estoy deseando saber cuántos milisegundos utiliza una función en particular. Así que miré alto y bajo, pero no pude encontrar la manera de pasar el tiempo en Ruby con una precisión de milisegundos.Cómo sincronizar una operación en milisegundos en Ruby?

¿Cómo se hace esto? En la mayoría de los lenguajes de programación es sólo algo así como

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

Respuesta

76

Puede usar la clase Time de ruby. Por ejemplo:

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

Ahora, delta es un objeto float y se puede obtener como resultado de grano fino que la clase va a dar.

13

Usted debe echar un vistazo al módulo de referencia para llevar a cabo los puntos de referencia. Sin embargo, como un método de sincronización rápida y sucia se puede usar algo como esto:

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

Nota el uso de Time.now.to_f, que a diferencia to_i, pero sin truncar al segundo.

+5

Los tiempos de fundición para flotar aquí son innecesarios. –

44

También puede utilizar el incorporado en función de Benchmark.measure:

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

Lienzo:

0.000000 0.000000 0.000000 ( 0.501134) 
+1

Me gusta la idea de usar una biblioteca incorporada, pero ¿cuáles son los primeros tres números (el '0.000000')? _Update: _ Lo buscó [en los documentos] (http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html) y es el tiempo de CPU del usuario, el tiempo de CPU del sistema y la suma de esos dos. – lyonsinbeta

+1

Sí. Están etiquetados si usa 'Benchmark.bm'. Es útil para ver dónde se gasta el tiempo a veces. Aquí puede ver que el bloque está al ralentí (0 en total, 0,5 reales) –

+10

O hay un 'Benchmark.realtime' que devuelve un único float comprensible :) –

1

El absolute_time joya es una gota en el reemplazo de referencia, pero utiliza las instrucciones nativas a ser mucho más preciso.

+1

o hitimes gem que puede tener mayor granularidad en windows que absolute_time ... – rogerdpack

0

El uso de Time.now.to_i devuelve el segundo aprobado desde 1970/01/01. Sabiendo esto se puede hacer

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

Con ello, tendrá que diferencia en segunda magnitud. Si quieres que en milisegundos, sólo tiene que añadir al código

diff = diff * 1000 
+2

'' '.to_i''' da un entero y truncaría los milisegundos. Esto funcionaría si simplemente lo cambiaras a '' '.to_f''' –

+1

Sí, como dice Ryan; Pedimos disculpas por el voto a la baja, pero esto en realidad tenía un voto positivo y me sentí obligado a contrarrestarlo. ¿Multiplicar una diferencia de tiempo _integer_ en segundos por 1000 para obtener milisegundos? Vamos, MARC.RS, ¡seguro que nos acabas de atrapar! :-) –

+0

No, solo hago mi mejor esfuerzo –

0

Si utiliza

date = Time.now.to_i 

que está obteniendo el tiempo en segundos, que es lejos de ser exacta, especialmente si usted está cronometrando pequeños trozos de código.

0

Tengo una gema que puede perfilar su método Ruby (instancia o clase) - https://github.com/igorkasyanchuk/benchmark_methods.

No más código como este:

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

Ahora se puede hacer:

benchmark :calculate_report # in class 

Y simplemente llame a su método de

user.calculate_report 
2

Usando Time.now (que devuelve el reloj de pared hora) como líneas base tiene un par de problemas que pueden provocar un comportamiento inesperado. Esto se debe al hecho de que el tiempo de reloj de pared está sujeto a cambios como segundos intercalares insertados o time slewing para ajustar la hora local a un tiempo de referencia.

Si, p. un segundo intercalar insertado durante la medición, se desactivará por un segundo. Del mismo modo, dependiendo de las condiciones del sistema local, es posible que tenga que lidiar con los horarios de ahorro de energía, los relojes que corren más rápido o más lento, o que el reloj retroceda en el tiempo, lo que da como resultado una duración negativa y muchos otros problemas.

Una solución a este problema es utilizar una hora diferente del reloj: un reloj monotónico. Este tipo de reloj tiene diferentes propiedades que el reloj de pared. Se incrementa monitónicamente, es decir, nunca retrocede y aumenta a una velocidad constante. Con eso, no representa el reloj de pared (es decir, el momento en que lee desde un reloj en su pared), sino una marca de tiempo que puede comparar con una marca de tiempo posterior para obtener una diferencia.

En Ruby, se puede utilizar una marca de tiempo con tales Process.clock_gettime(Process::CLOCK_MONOTONIC) gusta sigue:

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 

El método Process.clock_gettime devuelve una marca de tiempo como un flotador con fracciones de segundo. El número real devuelto no tiene un significado definido (en el que debe confiar). Sin embargo, puede estar seguro de que la próxima llamada devolverá un número mayor y al comparar los valores, puede obtener la diferencia de tiempo real.

Estos atributos hacen que el método sea un candidato ideal para medir las diferencias de tiempo sin ver su programa fallar en los momentos menos oportunos (por ejemplo, a medianoche en la víspera de Año Nuevo cuando se inserta otro segundo intercalado).

Cuestiones relacionadas