Pertanyaan Apakah mengunci dengan banyak objek yang berbeda memiliki dampak kinerja yang bijaksana dibandingkan dengan hanya satu?


Saya tidak tahu apakah pertanyaannya bodoh atau tidak, mengunci dan Monitor adalah kotak hitam bagi saya.

Tapi saya sedang menghadapi situasi di mana saya bisa menggunakan objek kunci yang sama untuk mengunci semuanya sepanjang waktu atau menggunakan jumlah objek yang tidak terbatas untuk mengunci pada tingkat butir yang lebih halus.

Saya tahu bahwa cara kedua akan mengurangi pertentangan kunci, tetapi saya mungkin akan menggunakan objek 10K sebagai kunci dan saya tidak tahu apakah itu memiliki dampak atau tidak.

Intinya: apakah terlalu banyak kunci yang merusak penguncian atau tidak berdampak?

Edit

Saya menulis lib yang menyimpan grafik objek, jumlahnya bisa sangat tinggi. Untuk saat ini tidak aman, terutama karena alasan Eric menyatakan dalam komentarnya.

Awalnya saya berpikir bahwa jika pengguna ingin melakukan multi-threading maka dia harus mengurus penguncian.

Tapi sekarang saya bertanya-tanya apakah saya harus membuatnya aman, apa yang akan menjadi cara terbaik untuk melakukannya (perhatikan bahwa membuat thread-safe tidak akan menjadi perjalanan yang singkat dan mudah bagi saya sehingga menguji kedua solusi adalah sesuatu yang tidak bisa saya lakukan dengan mudah)?

Karena tujuannya adalah untuk membuat setiap objek dari grafik tidak aman, maka saya dapat menggunakan instance objek untuk kunci ketika saya ingin mengakses / memodifikasi propertinya. Saya tahu ini adalah cara terbaik untuk mengurangi perselisihan, tetapi saya tidak tahu apakah itu akan menskalakan sebanyak hanya memiliki satu kunci untuk seluruh grafik.

Saya tahu ada banyak hal yang perlu dipertimbangkan, berapa banyak thread dan khususnya (saya pikir) kemungkinan sebuah objek sedang diakses / diubah oleh banyak utas sekaligus (yang saya perkirakan sangat rendah). Tetapi saya tidak dapat menemukan informasi akurat tentang kunci dan overhead mereka dalam kasus seperti itu.


8
2017-08-21 21:15


asal


Jawaban:


Untuk mendapatkan pandangan yang lebih jelas tentang apa yang terjadi, saya melihat kode sumber Monitor kelas dan mitra C ++ di clr/src/vm/syncblk.cpp dalam Shared Source Common Language Infrastructure dirilis oleh Microsoft.

Untuk menjawab pertanyaan saya sendiri: tidak, memiliki banyak kunci tidak sakit dengan cara berbahaya apa pun yang dapat saya pikirkan.

Apa yang saya pelajari:

1) Kunci yang sudah diambil oleh utas yang sama diproses "hampir gratis".

2) Kunci yang diambil untuk pertama kalinya pada dasarnya adalah biaya a InterlockedCompareExchange.

3) Beberapa utas yang menunggu kunci cukup murah untuk dilacak (daftar tautan dipertahankan, O (1) kerumitan).

4) Benang yang menunggu kunci untuk dilepaskan sejauh ini merupakan kasus penggunaan yang paling mahal, impuls pertama yang harus dikeluarkan untuk mencoba keluar, tetapi jika itu tidak cukup akan terjadi sakelar ulir, menempatkan utas untuk tidur sampai sinyal mutex waktu untuk bangun karena rilis kunci.

Saya mendapatkan jawaban saya dengan menggali 2): jika Anda selalu mengunci dengan objek yang sama atau 10K yang berbeda, pada dasarnya sama (ekstra inisialisasi dilakukan pertama kali Anda mengunci objek yang diberikan, tapi itu tidak terlalu buruk) . The InterlockedCompareExchange tidak peduli dipanggil di lokasi memori yang sama atau berbeda (AFAIK).

Pertentangan sejauh ini merupakan hal yang paling penting. Memiliki banyak kunci akan mengurangi (secara drastis dalam kasus saya) kemungkinan pertentangan, jadi itu hanya bisa menjadi hal yang baik.

1) juga pelajaran penting yang dipelajari: jika saya mengunci / membuka kunci untuk setiap perubahan / akses properti, saya dapat meningkatkan kinerja dengan mengunci objek terlebih dahulu, lalu mengubah banyak properti dan melepaskan kunci. Dengan cara ini hanya akan ada satu InterlockedCompareExchange dan kunci / buka kunci di dalam implementasi perubahan / akses properti hanya akan menambah penghitung internal.

Untuk menggali lebih dalam saya harus mencari informasi lebih lanjut tentang implementasi InterlockedCompareExchange, saya pikir itu bergantung pada instruksi perakitan CPU tertentu ...


4
2017-08-24 20:49



Biasanya, masalah kinerja sekitar penguncian terkait dengan pertikaian. Mendapatkan kunci yang tidak terbantahkan adalah pada urutan 10 detik nanodetik. Kontes adalah pembunuh berkinerja nyata. Seperti yang Anda tunjukkan, memiliki lebih banyak kunci (granularity kunci yang lebih tinggi) dapat meningkatkan kinerja dengan mengurangi pertikaian.

Kelemahan untuk memiliki beberapa kunci biasanya manajemen kunci harus lebih kompleks. Jika beberapa kunci diperlukan untuk melakukan operasi ada kemungkinan peningkatan masalah kelaparan sumber daya seperti deadlock atau livelock. Pengelolaan kunci yang tepat, seperti menegakkan perintah akuisisi kunci, dapat mengurangi masalah ini.

Tidak ada rincian lebih lanjut, saya mungkin akan menggunakan satu kunci, karena penerapannya lebih sederhana dan memantau kinerja aplikasi saya secara dekat. Secara khusus ada. Penghitung kinerja NET terkait dengan mengunci pertentangan yang dapat membantu mendiagnosa / mendeteksi masalah terkait pertentangan kunci.


1
2017-08-21 21:30



Seperti semua jawaban terkait kinerja saya ingin mengacu pada ini posting blog excepional oleh Eric Lippert, tergantung. Lihatlah enam pertanyaannya, apa jawaban Anda? Coba apa yang terjadi selama kondisi Anda.

Jumlah core, contention, caching, dll, semuanya penting, jadi lihat apa yang terjadi untuk Anda dalam kasus Anda, sangat tidak mungkin untuk mengetahuinya terlebih dahulu.

Bagi yang tidak mengklik tautan; jalankan mereka kuda!

Saya tidak berbicara tentang kinerja seperti kecepatan di sini, tetapi lebih seperti apa yang terjadi ketika aplikasi telah berjalan untuk sementara waktu. Menurut Mengunci (Memantau) implementasi internal dalam .NET Implementasi Monitor cukup pintar. NET, sehingga memiliki kunci internal untuk setiap objek mungkin tampak pendekatan yang layak, karena Anda mengatakan objek dalam puluhan ribu dan bukan jutaan.

Intinya: apakah terlalu banyak kunci yang merusak penguncian atau tidak berdampak?

Bukan pada itu sendiri, tetapi mungkin alasan untuk melihat arsitektur program Anda, memiliki objek trilyun terkunci pada saat yang sama akan menyebabkan overhead sekalipun.


-1
2017-08-21 21:36