Adakah yang bisa menjelaskan secara singkat kepada saya bagaimana ARC bekerja? Saya tahu ini berbeda dari Pengumpulan Sampah, tetapi saya hanya bertanya-tanya bagaimana cara kerjanya.
Juga, jika ARC melakukan apa yang dilakukan GC tanpa menghalangi kinerja, lalu mengapa Java menggunakan GC? Mengapa tidak menggunakan ARC juga?
objective-c
cocoa-touch
garbage-collection
automatic-ref-counting
pengguna635064
sumber
sumber
Jawaban:
Setiap pengembang baru yang datang ke Objective-C harus mempelajari aturan kaku tentang kapan mempertahankan, melepaskan, dan objek autorelease. Aturan-aturan ini bahkan menentukan konvensi penamaan yang menyiratkan jumlah tetap objek yang dikembalikan dari metode. Manajemen memori di Objective-C menjadi kebiasaan kedua setelah Anda menerapkan aturan ini dengan hati-hati dan menerapkannya secara konsisten, tetapi bahkan pengembang Kakao yang paling berpengalaman pun akan tergelincir dari waktu ke waktu.
Dengan Clang Static Analyzer, para pengembang LLVM menyadari bahwa aturan-aturan ini cukup dapat diandalkan sehingga mereka dapat membangun alat untuk menunjukkan kebocoran memori dan overreleases dalam jalur yang diambil kode Anda.
Penghitungan referensi otomatis (ARC) adalah langkah logis berikutnya. Jika kompiler dapat mengenali di mana Anda harus menyimpan dan melepaskan objek, mengapa tidak memasukkannya untuk Anda? Tugas yang kaku dan berulang adalah apa yang dilakukan kompiler dan saudara-saudara mereka yang hebat. Manusia melupakan sesuatu dan membuat kesalahan, tetapi komputer jauh lebih konsisten.
Namun, ini tidak sepenuhnya membebaskan Anda dari kekhawatiran tentang manajemen memori pada platform ini. Saya menjelaskan masalah utama yang harus diperhatikan (mempertahankan siklus) dalam jawaban saya di sini , yang mungkin memerlukan sedikit pemikiran pada bagian Anda untuk menandai pointer lemah. Namun, itu kecil jika dibandingkan dengan apa yang Anda peroleh di ARC.
Bila dibandingkan dengan manajemen memori manual dan pengumpulan sampah, ARC memberi Anda yang terbaik dari kedua dunia dengan memotong kebutuhan untuk menulis kode penahan / pelepasan, namun tidak memiliki profil kehabisan memori dan gigi gergaji yang terlihat di lingkungan pengumpulan sampah. Tentang satu-satunya keuntungan pengumpulan sampah memiliki lebih dari ini adalah kemampuannya untuk berurusan dengan mempertahankan siklus dan fakta bahwa penugasan properti atom murah (seperti dibahas di sini ). Saya tahu saya mengganti semua kode Mac GC yang ada dengan implementasi ARC.
Seperti apakah ini dapat diperluas ke bahasa lain, tampaknya diarahkan pada sistem penghitungan referensi di Objective-C. Mungkin sulit untuk menerapkan ini pada Java atau bahasa lain, tapi saya tidak cukup tahu tentang detail kompiler tingkat rendah untuk membuat pernyataan definitif di sana. Mengingat bahwa Apple adalah pihak yang mendorong upaya ini dalam LLVM, Objective-C akan didahulukan kecuali pihak lain melakukan sumber daya signifikan mereka sendiri untuk ini.
Penyingkapan pengembang mengejutkan ini di WWDC, sehingga orang tidak menyadari bahwa hal seperti ini bisa dilakukan. Ini mungkin muncul di platform lain dari waktu ke waktu, tetapi untuk saat ini eksklusif untuk LLVM dan Objective-C.
sumber
ARC hanya memainkan old retain / release (MRC) dengan kompiler mencari tahu kapan harus memanggil retain / release. Ini akan cenderung memiliki kinerja yang lebih tinggi, penggunaan memori puncak yang lebih rendah, dan kinerja yang lebih dapat diprediksi daripada sistem GC.
Di sisi lain beberapa jenis struktur data tidak dimungkinkan dengan ARC (atau MRC), sementara GC dapat menanganinya.
Sebagai contoh, jika Anda memiliki kelas bernama simpul, dan simpul memiliki NSArray anak-anak, dan satu referensi ke induknya yang "hanya bekerja" dengan GC. Dengan ARC (dan penghitungan referensi manual juga) Anda memiliki masalah. Setiap simpul yang diberikan akan dirujuk dari anak-anaknya dan juga dari orang tuanya.
Suka:
Semua baik-baik saja saat Anda menggunakan A (katakanlah melalui variabel lokal).
Ketika Anda selesai dengan itu (dan B1 / B2 / B3), sistem GC pada akhirnya akan memutuskan untuk melihat segala sesuatu yang dapat ditemukan mulai dari stack dan register CPU. Ia tidak akan pernah menemukan A, B1, B2, B3 sehingga akan menyelesaikannya dan mendaur ulang memori ke objek lain.
Ketika Anda menggunakan ARC atau MRC, dan selesai dengan A itu memiliki refcount dari 3 (B1, B2, dan B3 semua referensi itu), dan B1 / B2 / B3 semua akan memiliki jumlah referensi 1 (A's NSArray memegang satu referensi ke setiap). Jadi semua benda itu tetap hidup meskipun tidak ada yang bisa menggunakannya.
Solusi umum adalah memutuskan salah satu dari referensi tersebut harus lemah (tidak berkontribusi pada jumlah referensi). Itu akan berfungsi untuk beberapa pola penggunaan, misalnya jika Anda mereferensikan B1 / B2 / B3 hanya melalui A. Namun dalam pola lain itu gagal. Misalnya jika Anda kadang-kadang akan memegang B1, dan berharap untuk naik kembali melalui pointer orangtua dan menemukan A. Dengan referensi yang lemah jika Anda hanya memegang B1, kaleng (dan biasanya akan) menguap, dan mengambil B2, dan B3 dengan itu.
Terkadang ini bukan masalah, tetapi beberapa cara yang sangat berguna dan alami untuk bekerja dengan struktur data yang kompleks sangat sulit digunakan dengan ARC / MRC.
Jadi ARC menargetkan jenis masalah yang sama dengan target GC. Namun ARC bekerja pada pola penggunaan yang lebih terbatas daripada GC, jadi jika Anda menggunakan bahasa GC (seperti Java) dan mencangkokkan sesuatu seperti ARC ke dalamnya, beberapa program tidak akan berfungsi lagi (atau setidaknya akan menghasilkan banyak memori yang ditinggalkan) , dan dapat menyebabkan masalah pertukaran serius atau kehabisan memori atau ruang swap).
Anda juga dapat mengatakan ARC menempatkan prioritas yang lebih besar pada kinerja (atau mungkin dapat diprediksi) sementara GC menempatkan prioritas yang lebih besar untuk menjadi solusi generik. Akibatnya, GC memiliki tuntutan CPU / memori yang kurang dapat diprediksi, dan kinerja yang lebih rendah (biasanya) dari ARC, tetapi dapat menangani pola penggunaan apa pun. ARC akan bekerja lebih baik untuk banyak pola penggunaan umum, tetapi untuk beberapa pola penggunaan (valid!) Akan jatuh dan mati.
sumber
foo = nil
.Sihir
Tetapi lebih khusus ARC bekerja dengan melakukan apa yang akan Anda lakukan dengan kode Anda (dengan perbedaan kecil tertentu). ARC adalah teknologi waktu kompilasi, tidak seperti GC yang runtime dan akan berdampak negatif pada kinerja Anda. ARC akan melacak referensi ke objek untuk Anda dan mensintesis metode retain / release / autorelease sesuai dengan aturan normal. Karena ARC ini juga dapat mengeluarkan hal-hal segera setelah tidak diperlukan lagi, daripada membuangnya ke kolam autorelease murni semata-mata untuk kepentingan konvensi.
Beberapa peningkatan lainnya termasuk meniadakan referensi yang lemah, menyalin blok secara otomatis ke tumpukan, mempercepat di seluruh papan (6x untuk kumpulan autorelease!).
Diskusi yang lebih terperinci tentang bagaimana semua ini bekerja dapat ditemukan di LLVM Docs on ARC.
sumber
Ini sangat bervariasi dari pengumpulan sampah. Pernahkah Anda melihat peringatan yang memberi tahu Anda bahwa Anda mungkin membocorkan objek pada garis yang berbeda? Pernyataan itu bahkan memberi tahu Anda pada baris apa Anda mengalokasikan objek. Ini telah diambil selangkah lebih maju dan sekarang dapat menyisipkan
retain
/release
pernyataan di lokasi yang tepat, lebih baik daripada kebanyakan programmer, hampir 100% dari waktu. Kadang-kadang ada beberapa contoh aneh benda yang ditahan yang perlu Anda bantu.sumber
Sangat dijelaskan dengan baik oleh dokumentasi pengembang Apple. Baca "Bagaimana ARC Bekerja"
Untuk mengetahui Diff. antara pengumpulan sampah dan ARC: Baca ini
sumber
ARC adalah fitur kompiler yang menyediakan manajemen objek memori secara otomatis.
Alih-alih Anda harus ingat kapan harus digunakan
retain, release
, danautorelease
, ARC mengevaluasi persyaratan seumur hidup dari objek Anda dan secara otomatis memasukkan panggilan manajemen memori yang sesuai untuk Anda pada waktu kompilasi. Kompiler juga menghasilkan metode dealloc yang sesuai untuk Anda.Kompiler memasukkan
retain/release
panggilan yang diperlukan pada waktu kompilasi, tetapi panggilan tersebut dijalankan pada saat runtime, sama seperti kode lainnya.Diagram berikut akan memberi Anda pemahaman yang lebih baik tentang cara kerja ARC.
Mereka yang baru dalam pengembangan iOS dan tidak memiliki pengalaman kerja pada Objective C. Silakan merujuk dokumentasi Apple untuk Panduan Pemrograman Manajemen Memori Lanjutan untuk pemahaman yang lebih baik tentang manajemen memori.
sumber