Comment chronométrer une opération en millisecondes dans Ruby?

Je souhaite savoir combien de millisecondes une fonction particulière utilise. J’ai donc regardé haut et bas, mais je n’ai pas trouvé le moyen d’obtenir le temps en Ruby avec une précision d’une 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 de Time ruby. Par exemple:

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

Maintenant, delta est un object float et vous pouvez obtenir un résultat aussi fin que le fournira la classe.

Vous pouvez également utiliser la fonction Benchmark.measure intégrée:

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

Impressions:

 0.000000 0.000000 0.000000 ( 0.501134) 

Vous devriez regarder le module de référence pour effectuer des tests de performances. Cependant, comme méthode de chronométrage 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é en secondes.

L’utilisation de Time.now (qui renvoie l’heure de l’horloge murale) en tant que lignes de base présente quelques problèmes qui peuvent entraîner un comportement inattendu. Cela est dû au fait que l’heure de l’horloge murale est sujette à des changements tels que les secondes intercalaires insérées ou le décalage temporel pour ajuster l’heure locale à une heure de référence.

Si, par exemple, une seconde bissextile est insérée pendant la mesure, celle-ci sera désactivée d’une seconde. De même, en fonction des conditions du système local, vous devrez peut-être faire face à l’heure d’été, à des horloges plus rapides ou plus lentes ou à une horloge remontant dans le temps, entraînant une durée négative et de nombreux autres problèmes.

Une solution à ce problème consiste à utiliser un temps d’horloge différent: une horloge monotone. Ce type d’horloge a des propriétés différentes de celles de l’horloge murale. Il s’incrémente de façon monitonique, c’est-à-dire qu’il ne revient jamais en arrière et augmente à un rythme constant. Avec cela, il ne représente pas l’horloge murale (c’est-à-dire l’heure que vous lisez depuis une horloge sur votre mur) mais un horodatage que vous pouvez comparer avec un horodatage ultérieur pour obtenir une différence.

Dans Ruby, vous pouvez utiliser un tel 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 en tant que valeur flottante avec des secondes fractionnelles. Le nombre réel renvoyé n’a pas de signification définie (sur laquelle vous devez vous appuyer). Cependant, vous pouvez être sûr que le prochain appel renverra un plus grand nombre et en comparant les valeurs, vous pourrez obtenir la différence en temps réel.

Ces atsortingbuts font de la méthode un candidat de choix pour mesurer les différences de temps sans voir votre programme échouer aux moments les moins opportuns (par exemple, à minuit à la veille du jour de l’année où une seconde de saut est insérée).

Utilisez Time.now.to_f

Le gem absolute_time est un remplacement instantané pour Benchmark, mais utilise des instructions natives pour être beaucoup plus précis.

Si tu utilises

 date = Time.now.to_i 

Vous obtenez du temps en secondes, ce qui est loin d’être exact, surtout si vous programmez de petits morceaux de code.

L’utilisation de Time.now.to_i retourne la seconde passée de 1970/01/01. Sachant cela, vous pouvez faire

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

Avec cela, vous aurez une différence de deuxième ampleur. Si vous le voulez en millisecondes , ajoutez simplement au code

 diff = diff * 1000 

J’ai un bijou qui peut profiler votre méthode Ruby (instance ou classe) – https://github.com/igorkasyanchuk/benchmark_methods .

Plus de code comme celui-ci:

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

Maintenant vous pouvez faire:

 benchmark :calculate_report # in class 

Et appelle ta méthode

 user.calculate_report