Come ottengo il tempo trascorso in millisecondi in Ruby?


98

Se ho un Timeoggetto ricevuto da:

Time.now

e successivamente istanzio un altro oggetto con quella stessa riga, come posso vedere quanti millisecondi sono passati? Il secondo oggetto può essere creato nello stesso minuto, nei minuti successivi o anche nelle ore.

Risposte:


133

Come già affermato, è possibile operare sugli Timeoggetti come se fossero valori numerici (o in virgola mobile). Queste operazioni danno come risultato una seconda risoluzione che può essere facilmente convertita.

Per esempio:

def time_diff_milli(start, finish)
   (finish - start) * 1000.0
end

t1 = Time.now
# arbitrary elapsed time
t2 = Time.now

msecs = time_diff_milli t1, t2

Dovrai decidere se troncarlo o meno.


2
aggiungi un to_i e lo avrai come numero intero, ad esempio: ((finish - start) * 1000.0) .to_i
Travis Reeder

finish.to_f - start.to_f?
bodacious

1
finish - startrestituisce virgola mobile; .to_fsarebbe ridondante.
ezpz

5
Se utilizzi rails o supporto attivo, puoi utilizzare il metodo #in_milliseconds per eseguire la stessa conversione(t2 - t1).in_milliseconds
Nathan Hanna,

58

Puoi aggiungere un po 'di zucchero di sintassi alla soluzione sopra con quanto segue:

class Time
  def to_ms
    (self.to_f * 1000.0).to_i
  end
end

start_time = Time.now
sleep(3)
end_time = Time.now
elapsed_time = end_time.to_ms - start_time.to_ms  # => 3004

31

Penso che la risposta sia stata scelta in modo errato, quel metodo dà secondi, non millisecondi.

t = Time.now.t­o_f
=> 1382471965.146

Qui suppongo che il valore fluttuante siano i millisecondi


1
La risposta scelta è corretta. L'uso dell'addizione o della sottrazione su Time.nowsta trattando il tempo come valori in virgola mobile con secondi prima del punto decimale e fino a nanosecondi dopo il punto decimale (sebbene nsec potrebbe non essere completamente accurato). Quindi moltiplicando quel valore per si 1000.0ottengono millisecondi.
dfherr

sì, ma dare solo "Time.now" è impreciso e non risponde con precisione alla domanda.
LowFieldTheory

12

Per ottenere il tempo in millisecondi, è meglio aggiungere .round(3), quindi in alcuni casi sarà più preciso:

puts Time.now.to_f # => 1453402722.577573

(Time.now.to_f.round(3)*1000).to_i  # => 1453402722578

9

La risposta di ezpz è quasi perfetta, ma spero di poter aggiungere qualcosina in più.

Geo ha chiesto informazioni sul tempo in millisecondi; questo suona come una quantità intera e non prenderei la deviazione attraverso la terra in virgola mobile. Quindi il mio approccio sarebbe:

irb(main):038:0> t8 = Time.now
=> Sun Nov 01 15:18:04 +0100 2009
irb(main):039:0> t9 = Time.now
=> Sun Nov 01 15:18:18 +0100 2009
irb(main):040:0> dif = t9 - t8
=> 13.940166
irb(main):041:0> (1000 * dif).to_i
=> 13940

La moltiplicazione per un numero intero 1000 preserva perfettamente il numero frazionario e può essere anche un po 'più veloce.

Se hai a che fare con date e ore, potresti dover utilizzare la classe DateTime . Funziona in modo simile, ma il fattore di conversione è 24 * 3600 * 1000 = 86400000 .

Ho trovato le funzioni strptime e strftime di DateTime inestimabili per l'analisi e la formattazione delle stringhe di data / ora (ad esempio da / a log). Ciò che è utile sapere è:

  • I caratteri di formattazione per queste funzioni (% H,% M,% S, ...) sono quasi gli stessi delle funzioni C presenti su qualsiasi sistema Unix / Linux; e

  • Ce ne sono altri: in particolare, % L fa millisecondi!


Buono a sapersi! Grazie unknown:)
Geo

1
Comunque% L ​​esiste solo in Ruby 1.9;)
Rafa de Castro

7
DateTime.now.strftime("%Q")

Utilizzo di esempio:

>> DateTime.now.strftime("%Q")
=> "1541433332357"

>> DateTime.now.strftime("%Q").to_i
=> 1541433332357

6

Time.now.to_f può aiutarti ma restituisce secondi.

In generale, quando si lavora con i benchmark:

  • mettere in variabile l'ora corrente;
  • inserire il blocco da testare;
  • inserire in una variabile l'ora corrente, sottraendo il valore dell'ora corrente precedente;

È un processo molto semplice, quindi non sono sicuro che lo stessi chiedendo davvero ...


6

%L dà millisecondi in rubino

require 'time'
puts Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L")

o

puts Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")

ti darà il timestamp corrente in millisecondi.


Questo non dice come ottenere il tempo trascorso.
Robert

4

La risposta è qualcosa del tipo:

t_start = Time.now
# time-consuming operation
t_end = Time.now

milliseconds = (t_start - t_end) * 1000.0

Tuttavia, l' Time.nowapproccio rischia di essere impreciso. Ho trovato questo post di Luca Guidi:

https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/

l'orologio di sistema è costantemente fluttuante e non si sposta solo in avanti. Se il calcolo del tempo trascorso si basa su di esso, è molto probabile che si verifichino errori di calcolo o addirittura interruzioni .

Quindi, si consiglia di utilizzare Process.clock_gettimeinvece. Qualcosa di simile a:

def measure_time
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed_time = end_time - start_time
  elapsed_time.round(3)
end

Esempio:

elapsed = measure_time do
    # your time-consuming task here:
    sleep 2.2321
end

=> 2.232

3

Prova a sottrarre il primo Time.now dal secondo. Così:

a = Time.now
sleep(3)
puts Time.now - a # about 3.0

Questo ti dà un numero in virgola mobile dei secondi tra le due volte (e con questo, i millisecondi).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.