Kepemilikan Bersama Jarang Masuk Akal
Jawaban ini mungkin sedikit menyinggung, tetapi saya harus bertanya, berapa banyak kasus yang masuk akal dari sudut pandang pengguna-akhir untuk berbagi kepemilikan ? Setidaknya dalam domain tempat saya bekerja, hampir tidak ada domain karena jika tidak, itu berarti bahwa pengguna tidak perlu hanya menghapus sesuatu satu kali dari satu tempat, tetapi secara eksplisit menghapusnya dari semua pemilik yang relevan sebelum sumber daya sebenarnya dihapus dari sistem.
Ini sering merupakan ide rekayasa tingkat rendah untuk mencegah sumber daya tidak dihancurkan sementara sesuatu yang lain masih mengaksesnya, seperti utas lainnya. Seringkali ketika pengguna meminta untuk menutup / menghapus / menghapus sesuatu dari perangkat lunak, itu harus dihapus sesegera mungkin (setiap kali aman untuk dihapus), dan itu pasti tidak boleh berlama-lama dan menyebabkan kebocoran sumber daya selama aplikasi sedang berjalan.
Sebagai contoh, aset gim dalam gim video mungkin merujuk materi dari pustaka materi. Kami tentu saja tidak ingin, misalnya, crash pointer menggantung jika materi dihapus dari perpustakaan materi dalam satu utas sementara utas lainnya masih mengakses materi yang dirujuk oleh aset game. Tapi itu tidak berarti masuk akal bagi aset game untuk berbagi kepemilikan materi yang mereka rujuk dengan perpustakaan materi. Kami tidak ingin memaksa pengguna untuk menghapus materi secara eksplisit dari pustaka aset dan material. Kami hanya ingin memastikan bahwa bahan tidak dihapus dari perpustakaan materi, satu-satunya pemilik bahan yang masuk akal, sampai utas lainnya selesai mengakses materi.
Kebocoran Sumber Daya
Namun saya bekerja dengan mantan tim yang merangkul GC untuk semua komponen dalam perangkat lunak. Dan sementara itu benar-benar membantu memastikan kami tidak pernah menghancurkan sumber daya sementara utas lainnya masih mengaksesnya, kami malah mendapatkan bagian kami dari kebocoran sumber daya .
Dan ini bukan kebocoran sumber daya sepele dari jenis yang hanya mengganggu pengembang, seperti kilobyte memori yang bocor setelah sesi selama satu jam. Ini adalah kebocoran epik, sering gigabyte memori selama sesi aktif, yang mengarah ke laporan bug. Karena sekarang ketika kepemilikan sumber daya sedang direferensikan (dan karenanya dibagikan kepemilikan) di antara, katakanlah, 8 bagian sistem yang berbeda, maka hanya diperlukan satu untuk gagal menghapus sumber daya sebagai tanggapan terhadap pengguna yang meminta agar dihapus untuk itu. menjadi bocor dan mungkin tanpa batas.
Jadi saya tidak pernah menjadi penggemar berat GC atau penghitungan referensi yang diterapkan pada skala luas karena betapa mudahnya mereka membuat perangkat lunak yang bocor. Apa yang tadinya adalah crash pointer menjuntai yang mudah dideteksi berubah menjadi kebocoran sumber daya yang sangat sulit dideteksi yang dapat dengan mudah terbang di bawah radar pengujian.
Referensi yang lemah dapat mengurangi masalah ini jika bahasa / pustaka menyediakan ini, tetapi saya merasa sulit untuk mendapatkan tim pengembang wajan campuran untuk dapat secara konsisten menggunakan referensi yang lemah kapan pun sesuai. Dan kesulitan ini tidak hanya terkait dengan tim internal, tetapi untuk setiap pengembang plugin tunggal untuk perangkat lunak kami. Mereka juga dapat dengan mudah menyebabkan sistem membocorkan sumber daya dengan hanya menyimpan referensi terus-menerus ke suatu objek dengan cara yang membuatnya sulit untuk melacak kembali ke plugin sebagai pelakunya, jadi kami juga mendapat bagian terbesar dari laporan bug yang dihasilkan dari sumber daya perangkat lunak kami bocor hanya karena plugin yang kode sumbernya di luar kendali kami gagal merilis referensi ke sumber daya yang mahal itu.
Solusi: Ditangguhkan, Penghapusan Berkala
Jadi solusi saya nanti yang saya terapkan pada proyek pribadi saya yang memberi saya jenis yang terbaik yang saya temukan dari kedua dunia adalah untuk menghilangkan konsep itu referencing=ownership
tetapi masih menunda kerusakan sumber daya.
Akibatnya, sekarang setiap kali pengguna melakukan sesuatu yang menyebabkan sumber daya perlu dihapus, API dinyatakan dalam hal hanya menghapus sumber daya:
ecs->remove(component);
... yang memodelkan logika pengguna-akhir dengan cara yang sangat mudah. Namun, sumber daya (komponen) tidak dapat dihapus segera jika ada utas sistem lainnya dalam fase pemrosesan mereka di mana mereka dapat mengakses komponen yang sama secara bersamaan.
Jadi utas pemrosesan ini kemudian menghasilkan waktu di sana-sini yang memungkinkan utas yang menyerupai pengumpul sampah untuk bangun dan " menghentikan dunia " dan menghancurkan semua sumber daya yang diminta untuk dihapus sambil mengunci keluar benang dari memproses komponen-komponen tersebut sampai selesai . Saya telah menyetel ini sehingga jumlah pekerjaan yang perlu dilakukan di sini pada umumnya minimal dan tidak memangkas laju bingkai.
Sekarang saya tidak bisa mengatakan ini adalah metode yang telah dicoba dan diuji dan didokumentasikan dengan baik, tetapi ini adalah sesuatu yang telah saya gunakan selama beberapa tahun sekarang tanpa sakit kepala sama sekali dan tidak ada kebocoran sumber daya. Saya sarankan mengeksplorasi pendekatan seperti ini ketika arsitektur Anda mungkin cocok dengan model konkurensi seperti ini karena jauh lebih ringan daripada GC atau penghitungan ulang dan tidak mengambil risiko kebocoran sumber daya jenis ini terbang di bawah radar pengujian.
Satu tempat di mana saya menemukan penghitungan ulang atau GC berguna adalah untuk struktur data yang persisten. Dalam hal ini adalah wilayah struktur data, jauh terpisah dari masalah pengguna akhir, dan di sana sebenarnya masuk akal untuk setiap salinan yang tidak berubah untuk berpotensi berbagi kepemilikan atas data yang tidak dimodifikasi yang sama.