Comment obtenir le temps écoulé en millisecondes dans Ruby?

98

Si j'ai un Timeobjet provenant de:

Time.now

et plus tard j'instancie un autre objet avec cette même ligne, comment puis-je voir combien de millisecondes se sont écoulées? Le deuxième objet peut être créé à la même minute, au cours des prochaines minutes ou même des heures.

Géo
la source

Réponses:

133

Comme indiqué déjà, vous pouvez opérer sur Time objets comme s'il s'agissait de valeurs numériques (ou à virgule flottante). Ces opérations aboutissent à une seconde résolution qui peut être facilement convertie.

Par exemple:

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

Vous devrez décider de tronquer cela ou non.

ezpz
la source
2
ajoutez un to_i et vous l'avez sous forme d'entier, par exemple: ((finish - start) * 1000.0) .to_i
Travis Reeder
finish.to_f - start.to_f?
bodacious
1
finish - startdonne une virgule flottante; .to_fserait redondant.
ezpz
5
Si vous utilisez des rails ou un support actif, vous pouvez utiliser la méthode #in_milliseconds pour faire la même conversion(t2 - t1).in_milliseconds
Nathan Hanna
58

Vous pouvez ajouter un peu de sucre de syntaxe à la solution ci-dessus avec ce qui suit:

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
phlipper
la source
31

Je pense que la réponse est mal choisie, cette méthode donne des secondes, pas des millisecondes.

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

Ici, je suppose que la valeur flottante correspond aux millisecondes

LowFieldTheory
la source
1
La réponse choisie est correcte. L'utilisation de l'addition ou de la soustraction Time.nowconsiste à traiter le temps comme des valeurs à virgule flottante avec des secondes avant le point décimal et jusqu'à nanosecondes après le point décimal (bien que nsec puisse ne pas être complètement précis). Donc, multiplier cette valeur par 1000.0donne des millisecondes.
dfherr le
oui, mais donner juste "Time.now" est inexact et ne répond pas précisément à la question.
LowFieldTheory
12

Pour obtenir le temps en millisecondes, il vaut mieux ajouter .round(3), donc ce sera plus précis dans certains cas:

puts Time.now.to_f # => 1453402722.577573

(Time.now.to_f.round(3)*1000).to_i  # => 1453402722578
Steven Yue
la source
9

La réponse d'ezpz est presque parfaite, mais j'espère pouvoir en ajouter un peu plus.

Geo a demandé le temps en millisecondes; cela ressemble à une quantité entière, et je ne ferais pas le détour par la terre en virgule flottante. Ainsi mon approche serait:

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 multiplication par un entier 1000 préserve parfaitement le nombre fractionnaire et peut être un peu plus rapide aussi.

Si vous traitez avec des dates et des heures, vous devrez peut-être utiliser la classe DateTime . Cela fonctionne de la même manière mais le facteur de conversion est 24 * 3600 * 1000 = 86400000 .

J'ai trouvé les fonctions strptime et strftime de DateTime inestimables dans l'analyse et le formatage des chaînes de date / heure (par exemple vers / depuis les journaux). Ce qu'il est utile de savoir, c'est:

  • Les caractères de formatage pour ces fonctions (% H,% M,% S, ...) sont presque les mêmes que pour les fonctions C trouvées sur n'importe quel système Unix / Linux; et

  • Il y en a quelques autres: en particulier, % L fait des millisecondes!

Carl Smotricz
la source
Bon à savoir! Merci unknown:)
Geo
1
Quoi qu'il en soit,% L n'existe que dans Ruby 1.9;)
Rafa de Castro
7
DateTime.now.strftime("%Q")

Exemple d'utilisation:

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

>> DateTime.now.strftime("%Q").to_i
=> 1541433332357
Ryan McGeary
la source
6

Time.now.to_f peut vous aider mais il renvoie des secondes.

En général, lorsque je travaille avec des benchmarks, je:

  • mettre en variable l'heure actuelle;
  • insérez le bloc à tester;
  • mettre dans une variable l'heure actuelle, en soustrayant la valeur d'instant courant précédente;

C'est un processus très simple, donc je ne suis pas sûr que vous ayez vraiment posé cette question ...


la source
6

%L donne des millisecondes en rubis

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

ou

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

vous donnera l'horodatage actuel en millisecondes.

Sandeep Singh Nagra
la source
Cela ne dit pas comment obtenir le temps écoulé.
Robert
4

La réponse est quelque chose comme:

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

milliseconds = (t_start - t_end) * 1000.0

Cependant, l' Time.nowapproche risque d'être inexacte. J'ai trouvé ce post de Luca Guidi:

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

L'horloge du système flotte constamment et ne se déplace pas seulement vers l'avant. Si votre calcul du temps écoulé est basé sur celui-ci, vous risquez très probablement de rencontrer des erreurs de calcul ou même des pannes .

Donc, il est recommandé d'utiliser à la Process.clock_gettimeplace. Quelque chose comme:

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

Exemple:

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

=> 2.232
Robert
la source
3

Essayez de soustraire le premier Time.now du second. Ainsi:

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

Cela vous donne un nombre à virgule flottante des secondes entre les deux heures (et avec cela, les millisecondes).

mrueg
la source