メソッドとRubyのそのメソッドの個々のステートメントにかかる時間をどのように測定できますか?以下のメソッドが表示される場合、メソッドにかかった合計時間と、データベースアクセスとredisアクセスにかかった時間を測定します。すべてのステートメントの前にBenchmark.measureを書きたくありません。 Rubyインタープリターはこれを行うためのフックを提供しますか?
def foo
# code to access database
# code to access redis.
end
Time
オブジェクトを使用できます。 ( Time Docs )
例えば、
start = Time.now
# code to time
finish = Time.now
diff = finish - start
diff
は、浮動小数点数としての秒単位です。
編集:end
は予約されています。
最も簡単な方法:
require 'benchmark'
def foo
time = Benchmark.measure {
code to test
}
puts time.real #or save it to logs
end
サンプル出力:
2.2.3 :001 > foo
5.230000 0.020000 5.250000 ( 5.274806)
値は、CPU時間、システム時間、合計および実際の経過時間です。
ソース: Ruby docs 。
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
これにより、次のようなものが出力されます。
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.
詳細情報を見つけることができます ここ 。
考え直して、measure()関数をRubyコードブロック引数と一緒に定義すると、時間測定コードを簡素化できます。
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
答えの多くは、Time.now
。ただし、Time.now
変えられる。システムクロックはドリフトする可能性があり、システムの管理者またはNTPによって修正される場合があります。そのため、Time.nowが前後にジャンプして、ベンチマークの結果が不正確になる可能性があります。
より良い解決策は、常に前進しているオペレーティングシステムの単調クロックを使用することです。 Ruby 2.1以降では、次の方法でこれにアクセスできます。
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
詳細を読むことができます こちら 。また、人気のあるRubyプロジェクト、Sidekiq、 単調時計 に切り替えたことがわかります。
Ruby-prof
パッケージには、必要なものが含まれているはずです。タイミングを持つ巨大な呼び出しスタックを作成します。
http://Ruby-prof.rubyforge.org/
粒度が細かすぎる可能性があります。その場合、Benchmark.measure
は良い方法かもしれません。
wquist's answer の精神ではありますが、もう少し簡単に、以下のようにすることもできます。
start = Time.now
# code to time
Time.now - start