Apa cara standar untuk membuat profil panggilan metode Scala?
Yang saya butuhkan adalah kait di sekitar metode, yang dapat digunakan untuk memulai dan menghentikan Timer.
Di Java saya menggunakan pemrograman aspek, aspekJ, untuk menentukan metode yang akan diprofilkan dan menyuntikkan bytecode untuk mencapai hal yang sama.
Apakah ada cara yang lebih alami di Scala, di mana saya dapat menentukan banyak fungsi yang akan dipanggil sebelum dan sesudah suatu fungsi tanpa kehilangan pengetikan statis apa pun dalam prosesnya?
Jawaban:
Apakah Anda ingin melakukan ini tanpa mengubah kode yang ingin Anda ukur pengaturan waktunya? Jika Anda tidak keberatan mengubah kodenya, Anda dapat melakukan sesuatu seperti ini:
sumber
t1
dalamfinally
klausadef time[R](label: String)(block: => R): R = {
lalu tambahkan label keprintln
Selain jawaban Jesper, Anda dapat secara otomatis menggabungkan pemanggilan metode di REPL:
Sekarang - mari kita bungkus apa pun di sini
OK - kita harus dalam mode daya
Bungkus
Saya tidak tahu mengapa barang-barang itu dicetak 5 kali
Pembaruan pada 2.12.2:
sumber
:wrap
fitur tersebut telah dihapus dari REPL: - \Ada tiga pustaka pembandingan untuk Scala yang dapat Anda manfaatkan.
Karena URL di situs tertaut cenderung berubah, saya menempelkan konten yang relevan di bawah ini.
SPerformance - Kerangka kerja Pengujian Kinerja yang bertujuan untuk membandingkan pengujian kinerja secara otomatis dan bekerja di dalam Simple Build Tool.
scala-benchmarking-template - Proyek template SBT untuk membuat benchmark Scala (mikro-) berdasarkan Caliper.
Metrik - Menangkap JVM- dan metrik tingkat aplikasi. Jadi Anda tahu apa yang sedang terjadi
sumber
Ini yang saya gunakan:
sumber
testing.Benchmark
semoga bermanfaat.sumber
Saya mengambil solusi dari Jesper dan menambahkan beberapa agregasi padanya di beberapa menjalankan kode yang sama
Misalkan Anda ingin mengatur waktu dua fungsi
counter_new
dancounter_old
, berikut ini adalah penggunaan:Semoga bermanfaat
sumber
Saya menggunakan teknik yang mudah dipindahkan dalam blok kode. Intinya adalah baris yang sama persis memulai dan mengakhiri pengatur waktu - jadi ini benar-benar merupakan salin dan tempel sederhana. Hal baik lainnya adalah Anda bisa mendefinisikan apa arti timing bagi Anda sebagai string, semuanya dalam baris yang sama.
Contoh penggunaan:
Kode:
Kelebihan:
Kekurangan:
sumber
Timelog.timer("timer name/description")
?ScalaMeter adalah pustaka yang bagus untuk melakukan benchmarking di Scala
Di bawah ini adalah contoh sederhana
Jika Anda mengeksekusi potongan kode di atas dalam Scala Worksheet Anda mendapatkan waktu berjalan dalam milidetik
sumber
Saya suka kesederhanaan jawaban @ wrick, tetapi juga menginginkan:
profiler menangani perulangan (untuk konsistensi dan kenyamanan)
pengaturan waktu yang lebih akurat (menggunakan nanoTime)
waktu per iterasi (bukan total waktu dari semua iterasi)
hanya mengembalikan ns / iterasi - bukan tupel
Ini dicapai di sini:
Untuk akurasi yang lebih tinggi, modifikasi sederhana memungkinkan loop pemanasan Hotspot JVM (bukan waktunya) untuk mengatur waktu cuplikan kecil:
sumber
Pendekatan yang direkomendasikan untuk membandingan kode Scala adalah melalui sbt-jmh
Pendekatan ini diambil oleh banyak proyek Scala besar, misalnya,
Sederhana wrapper waktu berdasarkan
System.nanoTime
adalah tidak metode yang dapat diandalkan dari pembandingan:Selain itu, pertimbangan seperti pemanasan JIT , pengumpulan sampah, peristiwa di seluruh sistem, dll. Mungkin menyebabkan ketidakpastian dalam pengukuran:
Berdasarkan jawaban Travis Brown berikut adalah contoh bagaimana mengatur benchmark JMH untuk Scala
project/plugins.sbt
build.sbt
Tambahkan
src/main/scala/bench/VectorAppendVsListPreppendAndReverse.scala
Hasilnya adalah
yang tampaknya menunjukkan prepending ke a
List
dan kemudian membalikkannya pada akhirnya adalah urutan besarnya lebih cepat daripada terus menambahkan ke aVector
.sumber
Sambil berdiri di pundak raksasa ...
Pustaka pihak ketiga yang solid akan lebih ideal, tetapi jika Anda membutuhkan sesuatu yang cepat dan berbasis pustaka std, varian berikut menyediakan:
.
Juga perlu diperhatikan Anda dapat menggunakan
Duration.toCoarsest
metode untuk mengonversi ke satuan waktu terbesar, meskipun saya tidak yakin seberapa ramah ini dengan perbedaan waktu kecil antara berjalan misalnyasumber
Kamu bisa memakai
System.currentTimeMillis
:Pemakaian:
nanoTime akan menunjukkannya kepada Anda
ns
, sehingga akan sulit dilihat. Jadi saya menyarankan agar Anda dapat menggunakan currentTimeMillis sebagai gantinya.sumber