web-dev-qa-db-fra.com

Mesurer et comparer le temps pour Ruby Méthodes

Comment puis-je mesurer le temps pris par une méthode et les instructions individuelles de cette méthode dans Ruby. Si vous voyez la méthode ci-dessous, je veux mesurer le temps total pris par la méthode et le temps pris pour l'accès à la base de données et l'accès redis. Je ne veux pas écrire Benchmark.measure avant chaque déclaration. L'interprète Ruby nous donne-t-il des crochets pour ce faire?

def foo
# code to access database
# code to access redis. 
end
72
Phani

Vous pouvez utiliser l'objet Time. ( Time Docs )

Par exemple,

start = Time.now
# code to time
finish = Time.now

diff = finish - start

diff serait en secondes, sous forme de nombre à virgule flottante.

EDIT: end est réservé.

101
wquist

La manière la plus simple:

require 'benchmark'

def foo
 time = Benchmark.measure {
  code to test
 }
 puts time.real #or save it to logs
end

Exemple de sortie:

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

Les valeurs sont les suivantes: temps processeur, temps système, temps total et temps réel écoulé.

Source: Ruby docs .

83
Łukasz Ostrowski

Utiliser le rapport de référence

require 'benchmark' # Might be necessary.

def foo
  Benchmark.bm(20) do |bm|  # The 20 is the width of the first column in the output.
    bm.report("Access Database:") do 
      # Code to access database.
    end

    bm.report("Access Redis:") do
      # Code to access redis.
    end
  end
end

Cela produira quelque chose comme ceci:

                        user     system      total        real
Access Database:    0.020000   0.000000   0.020000 (  0.475375)
Access Redis:       0.000000   0.000000   0.000000 (  0.000037)

<------ 20 ------->  # This is where the 20 comes in. NOTE: Not shown in output.

Plus d'informations peuvent être trouvées ici .

25
Joshua Pinter

Une deuxième réflexion, définissez la fonction measure () avec Ruby peut aider à simplifier le code de mesure du temps:

def measure(&block)
  start = Time.now
  block.call
  Time.now - start
end

# t1 and t2 is the executing time for the code blocks.
t1 = measure { sleep(1) }

t2 = measure do
  sleep(2)
end
6
Houcheng

De nombreuses réponses suggèrent l'utilisation de Time.now. Mais il faut savoir que Time.now Peut changer. Les horloges du système peuvent dériver et peuvent être corrigées par l'administrateur du système ou via NTP. Il est donc possible pour Time.now de sauter en avant ou en arrière et de donner à votre benchmarking des résultats inexacts.

Une meilleure solution consiste à utiliser l'horloge monotone du système d'exploitation, qui va toujours de l'avant. Ruby 2.1 et supérieur donnent accès à cela via:

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# code to time
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
diff = finish - start # gets time is seconds as a float

Vous pouvez lire plus de détails ici . Vous pouvez également voir le populaire Ruby, Sidekiq, est passé à horloge monotone .

5
Guy C

Regardez dans le Ruby-prof package, il devrait avoir ce dont vous avez besoin. Il créera d'énormes piles d'appels avec des horaires.

http://Ruby-prof.rubyforge.org/

Il peut être trop granulaire, auquel cas il suffit d'envelopper de plus grandes sections dans Benchmark.measure pourrait être une bonne façon de procéder.

3
Cody Caughlan

Dans l'esprit de réponse de wquist , mais un peu plus simple, vous pouvez également le faire comme ci-dessous:

start = Time.now
# code to time
Time.now - start
2
ADude2