Salah satu fitur praktis dari Scala adalah lazy val
, di mana evaluasi a val
ditunda sampai diperlukan (pada akses pertama).
Tentu saja, lazy val
harus memiliki beberapa overhead - di suatu tempat Scala harus melacak apakah nilai telah dievaluasi dan evaluasi harus disinkronkan, karena beberapa utas mungkin mencoba mengakses nilai untuk pertama kalinya pada waktu yang sama.
Apa sebenarnya biaya a lazy val
- apakah ada bendera boolean tersembunyi yang terkait dengan lazy val
untuk melacak apakah telah dievaluasi atau tidak, apa sebenarnya yang disinkronkan dan apakah ada biaya lagi?
Selain itu, misalkan saya melakukan ini:
class Something {
lazy val (x, y) = { ... }
}
Apakah ini sama dengan memiliki dua lazy val
s terpisah x
dan y
atau apakah saya mendapatkan overhead hanya sekali, untuk pasangan (x, y)
?
sumber
bitmap$0
bidang ini tidak stabil dalam implementasi saat ini (2.8).Tampaknya kompiler mengatur bidang int bitmap tingkat kelas untuk menandai beberapa bidang malas sebagai diinisialisasi (atau tidak) dan menginisialisasi bidang target dalam blok yang disinkronkan jika xor relevan dari bitmap menunjukkan perlunya.
Menggunakan:
menghasilkan bytecode sampel:
Nilai yang diinisialisasi dalam tupel seperti
lazy val (x,y) = { ... }
memiliki caching bersarang melalui mekanisme yang sama. Hasil tuple dievaluasi dan di-cache dengan malas, dan akses x atau y akan memicu evaluasi tuple. Ekstraksi nilai individu dari tuple dilakukan secara independen dan malas (dan di-cache). Jadi di atas kode double-Instansiasi menghasilkanx
,y
, danx$1
bidang jenisTuple2
.sumber
Dengan Scala 2.10, nilai malas seperti:
dikompilasi ke kode byte yang menyerupai kode Java berikut:
Perhatikan bahwa bitmap diwakili oleh a
boolean
. Jika Anda menambahkan bidang lain, kompiler akan menambah ukuran bidang agar dapat mewakili setidaknya 2 nilai, yaitu sebagai abyte
. Ini hanya berlaku untuk kelas besar.Tetapi Anda mungkin bertanya-tanya mengapa ini berhasil? Cache thread-local harus dihapus ketika memasuki blok yang disinkronkan sehingga nilai non-volatile
x
dimasukkan ke memori. Artikel blog ini memberikan penjelasan .sumber
Scala SIP-20 mengusulkan implementasi baru dari lazy val, yang lebih tepat tetapi ~ 25% lebih lambat dari versi "saat ini".
The pelaksanaan diusulkan terlihat seperti:
Per Juni 2013 SIP ini belum disetujui. Saya berharap bahwa itu kemungkinan akan disetujui dan dimasukkan dalam versi Scala mendatang berdasarkan diskusi milis. Karenanya, saya pikir Anda sebaiknya memperhatikan pengamatan Daniel Spiewak :
sumber
Saya telah menulis posting terkait masalah ini https://dzone.com/articles/cost-laziness
Singkatnya, hukumannya sangat kecil sehingga dalam praktiknya Anda bisa mengabaikannya.
sumber
diberi kode sandi yang dihasilkan oleh scala untuk lazy, ia dapat mengalami masalah keamanan utas seperti yang disebutkan dalam penguncian periksa ganda http://www.javaworld.com/javaworld/jw-05-2001/jw-0525-double.html?page=1
sumber