Je souhaite savoir combien de millisecondes une fonction particulière utilise. Je cherchais donc haut et bas, mais je ne pouvais pas trouver le moyen d’obtenir le temps en Ruby avec une précision milliseconde.
Comment est-ce que tu fais ça? Dans la plupart des langages de programmation, c'est juste quelque chose comme
start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start
Vous pouvez utiliser la classe Time
de Ruby. Par exemple:
t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds
Maintenant, delta
est un objet float
et vous pouvez obtenir un résultat aussi fin que le fournira la classe.
Vous pouvez également utiliser la fonction intégrée Benchmark.measure:
require "benchmark"
puts(Benchmark.measure { sleep 0.5 })
Impressions:
0.000000 0.000000 0.000000 ( 0.501134)
L'utilisation de Time.now
(qui renvoie l'heure de l'horloge murale) en tant que lignes de base pose quelques problèmes pouvant entraîner un comportement inattendu. Cela est dû au fait que l'heure murale est soumise à des modifications telles que l'insertion de secondes intercalaires ou le décalage temporel pour ajuster l'heure locale à une heure de référence.
S'il y a par exemple une seconde intercalaire insérée lors de la mesure, elle sera décalée d’une seconde. De même, en fonction des conditions du système local, vous devrez peut-être gérer l'heure avancée, des horloges plus rapides ou plus lentes ou même l'horloge qui saute dans le temps, ce qui entraîne une durée négative et bien d'autres problèmes.
Une solution à ce problème consiste à utiliser une horloge différente: une horloge monotone. Ce type d’horloge a des propriétés différentes de celles de l’horloge murale . Il s’incrémente monitonalement, c’est-à-dire qu’il ne remonte jamais et augmente à un taux constant. Avec cela, il ne représente pas l'horloge murale (c'est-à-dire l'heure à laquelle vous lisez une horloge sur votre mur), mais un horodatage que vous pouvez comparer à un horodatage ultérieur pour obtenir une différence.
En Ruby, vous pouvez utiliser un horodatage avec Process.clock_gettime(Process::CLOCK_MONOTONIC)
comme suit:
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
La méthode Process.clock_gettime
renvoie un horodatage sous forme de float avec des fractions de secondes. Le nombre réel renvoyé n'a pas de signification définie (sur laquelle vous devriez compter). Cependant, vous pouvez être sûr que le prochain appel renverra un nombre plus grand et en comparant les valeurs, vous pourrez obtenir la différence de temps réel.
Ces attributs font de la méthode un candidat idéal pour mesurer les différences de temps sans voir votre programme échouer aux heures les moins opportunes (par exemple, à minuit le soir du Nouvel An lorsqu'une autre seconde intercalaire est insérée).
La constante Process::CLOCK_MONOTONIC
utilisée ici est disponible sur tous les systèmes Linux, BSD et macOS modernes, ainsi que sur le sous-système Linux pour Windows. À ma connaissance, il n’est pas encore disponible pour les systèmes Windows "bruts". Là, vous pouvez utiliser l’appel GetTickCount
au lieu de Process.clock_gettime
, qui renvoie également une valeur de minuterie avec une granularité à la milliseconde sous Windows.
Vous devriez jeter un coup d'œil au module d'évaluation pour effectuer des analyses. Cependant, en tant que méthode de synchronisation rapide et sale, vous pouvez utiliser quelque chose comme ceci:
def time
now = Time.now.to_f
yield
endd = Time.now.to_f
endd - now
end
Notez l'utilisation de Time.now.to_f
, qui contrairement à to_i, ne sera pas tronqué à quelques secondes.
Utilisez Time.now.to_f
La gemme absolute_time
est un remplacement instantané de Benchmark, mais elle utilise des instructions natives pour être beaucoup plus précise.
Nous pouvons aussi créer une fonction simple pour enregistrer n’importe quel bloc de code:
def log_time
start_at = Time.now
yield if block_given?
execution_time = (Time.now - start_at).round(2)
puts "Execution time: #{execution_time}s"
end
log_time { sleep(2.545) } # Execution time: 2.55s
J'ai un bijou qui peut profiler votre méthode Ruby (instance ou classe) - https://github.com/igorkasyanchuk/benchmark_methods .
Pas plus de code comme ça:
t = Time.now
user.calculate_report
puts Time.now - t
Maintenant vous pouvez faire:
benchmark :calculate_report # in class
Et appelez juste votre méthode
user.calculate_report
L'utilisation de Time.now.to_i
renvoie la seconde passée du 1970/01 au 01/01. Sachant cela, tu peux le faire
date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1
Avec cela, vous aurez la différence en seconde magnitude. Si vous le souhaitez en millisecondes , ajoutez simplement le code
diff = diff * 1000
Si tu utilises
date = Time.now.to_i
Vous obtenez du temps en secondes, ce qui est loin d’être précis, en particulier si vous synchronisez de petits morceaux de code.