Mengukur dan Waktu Tolok Ukur untuk Metode Ruby

90

Bagaimana saya bisa mengukur waktu yang dibutuhkan oleh sebuah metode dan pernyataan individu dalam metode itu di Ruby. Jika Anda melihat metode di bawah ini, saya ingin mengukur total waktu yang dibutuhkan oleh metode dan waktu yang dibutuhkan untuk akses database dan akses redis. Saya tidak ingin menulis Benchmark.measure sebelum setiap pernyataan. Apakah penerjemah ruby ​​memberi kita kaitan untuk melakukan ini?

def foo
# code to access database
# code to access redis. 
end
Phani
sumber
ada sesuatu yang mirip dengan new Date()javascript yang dimiliki ruby, tetapi saya tidak dapat mengingat sintaks yang benar. harus memberi Anda daftar google yang layak meskipun
reagan
1
@Phani Bisakah Anda memilih jawaban yang benar? Setelah 8 tahun, saya pikir ada beberapa jawaban yang pasti di sini. Terima kasih.
Joshua Pinter

Jawaban:

118

Anda bisa menggunakan Timebenda itu. ( Dokumen Waktu )

Sebagai contoh,

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

diff = finish - start

diff akan menjadi dalam hitungan detik, sebagai angka floating point.

EDIT: endsudah dipesan.

wquist
sumber
14
hanya koreksi kecil. enddicadangkan, jadi gunakan beberapa nama variabel lainnya.
Jason Kim
5
Time.nowdipengaruhi oleh penyesuaian pada jam sistem, jadi sebaiknya gunakanlah praktik terbaik Process.clock_gettime(Process::CLOCK_MONOTONIC). Tetapi untuk perhitungan kasar ini tidak masalah. blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way
Patrick Brinich-Langlois
105

Cara termudah:

require 'benchmark'

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

Output sampel:

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

Nilai-nilainya adalah: waktu cpu, waktu sistem, total dan waktu yang telah berlalu.

Sumber: ruby docs .

Łukasz Ostrowski
sumber
41
Anda juga dapat melakukannya Benchmark.realtime { block }jika Anda hanya menginginkan realtime
jmccure
36

Gunakan BenchmarkLaporan

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

Ini akan menghasilkan sesuatu seperti berikut:

                        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: This is not shown in output.

Informasi lebih lanjut dapat ditemukan di sini .

Joshua Pinter
sumber
2
Saya baru saja kembali ke jawaban saya sendiri dan terkesan (lagi) dengan bagaimana Benchmark menangani ini. Cinta Ruby.
Joshua Pinter
2
Ini harus menjadi jawaban yang disukai: Karena, pada Ruby 2.2, Benchmarkkelas menggunakan jam monotonik, seperti yang dibahas dalam jawaban lain. Lihat misalnya kode sumber berikut, dan cari "ukuran def" pada baris 286: github.com/ruby/ruby/blob/ruby_2_2/lib/benchmark.rb
Purplejacket
19

Banyak dari jawaban menyarankan penggunaan Time.now. Tetapi perlu disadari bahwa itu Time.nowbisa berubah. Jam sistem dapat melayang dan mungkin dikoreksi oleh administrator sistem atau melalui NTP. Oleh karena itu, Time.now mungkin saja melompat maju atau mundur dan memberikan hasil yang tidak akurat kepada pembandingan Anda.

Solusi yang lebih baik adalah dengan menggunakan jam monotonik sistem operasi, yang selalu bergerak maju. Ruby 2.1 dan yang lebih baru memberikan akses ke ini melalui:

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

Anda dapat membaca lebih detail di sini . Anda juga dapat melihat proyek Ruby yang populer, Sidekiq, beralih ke jam monotonik .

Guy C
sumber
7

Pikiran kedua, tentukan fungsi measure () dengan argumen blok kode Ruby dapat membantu menyederhanakan kode pengukuran waktu:

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
Houcheng
sumber
Dalam definisi Anda, Anda menyebutnya benchmark. Saat Anda menggunakannya, itu disebut measure. Tolong perbaiki ini.
Sandro L
4

Dengan semangat jawaban wquist , tetapi sedikit lebih sederhana, Anda juga bisa melakukannya seperti di bawah ini:

start = Time.now
# code to time
Time.now - start
ADude2
sumber
Jawaban ini adalah cara yang (sedikit) berbeda untuk menjawab pertanyaan tersebut. Hanya karena Anda bisa mengetahuinya dari jawaban @ wquist tidak berarti itu tidak valid.
secretmaster
3

Lihatlah ke dalam ruby-profpaketnya, itu harus memiliki apa yang Anda butuhkan. Ini akan membuat tumpukan panggilan besar dengan pengaturan waktu.

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

Mungkin terlalu terperinci, dalam hal ini hanya membungkus bagian yang lebih besar Benchmark.measuremungkin merupakan cara yang baik untuk melakukannya.

Cody Caughlan
sumber
0

Metode lain bagaimana cara benchmark kode secara otomatis di konsol rel menggunakan permata ini: https://github.com/igorkasyanchuk/execution_time

Anda akan melihat info serupa seperti yang Anda dapatkan dari permintaan di log

Igor Kasyanchuk
sumber