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.

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.


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

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


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

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!


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

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 ...


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.


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

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).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.