2011-06-17 3 views
5

Como estoy haciendo algunas mediciones de tiempo en este momento, me preguntaba si es posible medir el tiempo del usuario o el sistema sin utilizar la clase Benchmark o la línea de comando utilidad time.Mide el tiempo de usuario o sistema en Ruby sin Benchmark o tiempo

El uso de la clase Time solo revela el tiempo del reloj de pared, no el sistema y el tiempo del usuario; sin embargo, estoy buscando una solución que tenga la misma flexibilidad, p.

time = TimeUtility.now 
# some code 
user, system, real = TimeUtility.now - time 

La razón es que de alguna manera me gusta Benchmark, ya que no puede devolver sólo números (EDIT: yo estaba equivocado - se puede ver respuestas a continuación..). Claro, podría analizar la salida, pero eso no parece correcto. La utilidad time de los sistemas * NIX también debería resolver mi problema, pero quería saber si ya existe algún tipo de envoltorio implementado en Ruby, así que no necesito hacer estas llamadas al sistema por mi cuenta.

¡Muchas gracias!

Respuesta

8

Releí la documentación de Benchmark y vi que tiene un método llamado measure. Este método hace exactamente lo que quiero: Medir el tiempo que necesita su código y devolver un objeto que contiene el tiempo de usuario, hora del sistema, hora del sistema de niños, etc. Es tan fácil como

require 'benchmark' 
measurement = Benchmark.measure do 
    # your code goes here 
end 

En el proceso descubrí que puede agregar filas personalizadas a la salida de Benchmark.Puede utilizar esto para conseguir lo mejor de ambos mundos (mediciones de tiempo personalizados y una bonita salida al final) de la siguiente manera:

require 'benchmark' 

measurements = [] 
10.times { measurements << Benchmark.measure { 1_000_000.times { a = "1" } } } 

# measurements.sum or measurements.inject(0){...} does not work, since the 
# array contains Benchmark instances, which cannot be coerced into Fixnum's 
# Array#sum will work if you are using Rails 
sum = measurements.inject(nil) { |sum, t| sum.nil? ? sum = t : sum += t } 
avg = sum/measurements.size 

# 7 is the width reserved for the description "sum:" and "avg:" 
Benchmark.bm(7, "sum:", "avg:") do |b| 
    [sum, avg] 
end 

El resultado se verá como la siguiente:

   user  system  total  real 
sum:  2.700000 0.000000 2.700000 ( 2.706234) 
avg:  0.270000 0.000000 0.270000 ( 0.270623) 
+0

Desearía que hubiera un atajo para 'requerir' punto de referencia '; Benchmark.measure {...} ' – dolzenko

+0

No entiendo, la parte citada es bastante corta. ¿Qué te gustaría? (Pseduo-Code permitido;) –

+0

seguro, probablemente no puede ser más corto que esto, fue lamentando la falta de algún atajo provisto con ruby ​​por defecto para guardar la escritura. + Siempre me olvido es 'measure' o' bm' o 'bmbm' o algo más :) – dolzenko

2

Puede usar la función Process::times, que devuelve el tiempo del usuario/hora del sistema. (No informa el tiempo del reloj de pared, necesitará algo más para eso). Parece ser una versión de bit o dependiente del sistema operativo.

Esto es lo que se informa en mi sistema (Linux, Ruby 1.8.7):

$ irb 
irb(main):001:0> t = Process.times 
=> #<struct Struct::Tms utime=0.01, stime=0.0, cutime=0.0, cstime=0.0> 

Los documentos muestran esto, sin embargo, por lo que algunas versiones/implementaciones pueden tener sólo los dos primeros:

t = Process.times 
[ t.utime, t.stime ] #=> [0.0, 0.02] 

Consulte times para la llamada subyacente en Linux.

Aquí es un envoltorio realmente horrible ese tipo de apoya -:

class SysTimes 

    attr_accessor :user, :system 

    def initialize 
     times = Process.times 
     @user = times.utime 
     @system = times.stime 
    end 

    def -(other) 
     diff = SysTimes.new 
     diff.user = @user - other.user 
     diff.system = @system - other.system 
     diff 
    end 
end 

deben darle ideas para hacer que funcione muy bien en su contexto.

+0

Lamentablemente es una estructura que no sabe cómo responder a '-', por lo tanto el tiempo =' Process.times; usuario, sistema = Process.times - time' generará un error. Sin embargo, no sabía acerca de este método antes y me gusta el enfoque, ya que puedo buscar cuánto tiempo mi programa se está ejecutando en cualquier punto del tiempo. :) Gracias por tu contribución! –

0

Esta joya podría ayudar: https://github.com/igorkasyanchuk/benchmark_methods

Ningún código de la misma familia:

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

Ahora usted puede hacer:

benchmark :calculate_report # in class 

Y simplemente llame a su método de

user.calculate_report 
Cuestiones relacionadas