2010-02-18 13 views
63

Desidero calcolare quanti millisecondi utilizza una particolare funzione. Così ho guardato in alto e in basso, ma non sono riuscito a trovare il modo di ottenere il tempo in Ruby con precisione millisecondo.Come cronometrare un'operazione in millisecondi in Ruby?

Come si fa? Nella maggior parte dei linguaggi di programmazione è solo qualcosa di simile

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

risposta

76

È possibile utilizzare la classe Time di Ruby. Per esempio:

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

Ora, delta è un oggetto float e si può ottenere a grana più fine un risultato come la classe fornirà.

1

Usa Time.now.to_f

13

Si dovrebbe dare un'occhiata al modulo di riferimento per eseguire benchmark. Tuttavia, come un metodo rapido e sporco di temporizzazione si può usare qualcosa di simile:

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

Nota l'uso di Time.now.to_f, che a differenza to_i, non troncherà a secondi.

+5

I tempi di lancio dei galleggianti qui non sono necessari. –

44

È inoltre possibile utilizzare il built-in funzione di Benchmark.measure:

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

Stampe:

0.000000 0.000000 0.000000 ( 0.501134) 
+1

Mi piace l'idea di usare una libreria incorporata, ma quali sono i primi tre numeri (il '0.000000')? _Aggiornamento: _ Lo ha cercato [nei documenti] (http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html) e il tempo della CPU dell'utente, il tempo della CPU del sistema e la somma di quei due. – lyonsinbeta

+1

Sì. Sono etichettati se usi 'Benchmark.bm'. È utile vedere a volte dove viene trascorso il tempo. Qui puoi vedere che il blocco è solo inattivo (0 totale, 0,5 reale) –

+10

Oppure c'è un 'Benchmark.realtime' che restituisce un singolo float comprensibile :) –

1

Il absolute_time gemma è un rimpiazzo per il Benchmark, ma utilizza istruzioni native per essere molto più accurato

+1

o hitimes gem che potrebbe avere una granularità più alta su windows rispetto a absolute_time ... – rogerdpack

0

L'utilizzo di Time.now.to_i restituisce il secondo passato dal 1970/01/01. Sapendo questo si può fare

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

Con questo si dovrà differenza in seconda grandezza. Se lo volete in millisecondi, basta aggiungere al codice

diff = diff * 1000 
+2

'' '.to_i''' restituisce un intero e troncerebbe i millisecondi. Funzionerebbe se lo avessi appena cambiato in '' '.to_f''' –

+1

Sì, come dice Ryan; mi scuso per il downvote, ma questo in realtà ha avuto un upvote e mi sono sentito in dovere di contrastarlo. Moltiplicando una differenza di tempo _integer_ in secondi per 1000 per ottenere millisecondi? Andiamo, MARC.RS, sicuramente ci stavi solo trollando! :-) –

+0

No, sto solo facendo del mio meglio –

0

Se si utilizza

date = Time.now.to_i 

che stai ottenendo il tempo in secondi, che è lontano dalla accurata, specialmente se si sono i tempi piccoli pezzi di codice.

0

Ho una gemma che può profilare il tuo metodo ruby ​​(istanza o classe) - https://github.com/igorkasyanchuk/benchmark_methods.

Non più codice come questo:

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

Ora si può fare:

benchmark :calculate_report # in class 

E basta chiamare il metodo

user.calculate_report 
2

Utilizzando Time.now (che restituisce l'orologio a muro tempo) come base-linee ha un paio di problemi che possono risultare in un comportamento imprevisto. Ciò è causato dal fatto che l'ora del wallclock è soggetta a modifiche come i secondi intercalati inseriti o time slewing per regolare l'ora locale a un orario di riferimento.

Se c'è, ad es. un secondo intercalare inserito durante la misurazione, sarà spento di un secondo. Allo stesso modo, a seconda delle condizioni del sistema locale, potrebbe essere necessario gestire l'ora legale, gli orologi più veloci o più lenti o l'orologio tornare indietro nel tempo, causando una durata negativa e molti altri problemi.

Una soluzione a questo problema consiste nell'utilizzare un orario diverso: un orologio monotono. Questo tipo di orologio ha proprietà diverse rispetto all'orologio da parete. Aumenta monitonicamente, cioè non torna mai indietro e aumenta ad una velocità costante. Con ciò, non rappresenta il wall-clock (cioè la volta che leggi da un orologio sul muro) ma un timestamp che puoi confrontare con un timestamp successivo per ottenere una differenza.

In Ruby, è possibile utilizzare tale timestamp con Process.clock_gettime(Process::CLOCK_MONOTONIC) piace segue:

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 

Il metodo Process.clock_gettime restituisce un timestamp come un galleggiante con frazioni di secondo. Il numero effettivo restituito non ha un significato definito (su cui dovresti fare affidamento). Tuttavia, puoi essere sicuro che la prossima chiamata restituirà un numero maggiore e confrontando i valori, puoi ottenere la differenza in tempo reale.

Questi attributi rendono il metodo un candidato ideale per misurare le differenze di tempo senza vedere il programma fallire nei tempi meno opportuni (ad esempio a mezzanotte a Capodanno quando è inserito un altro secondo intercalare).

Problemi correlati