Ke ARC atau tidak ke ARC? Apa pro dan kontranya? [Tutup]

113

Saya belum pernah menggunakan ARC, karena sebagian besar kode dalam proyek yang saya kerjakan saat ini ditulis sebelum iOS 5.0.

Saya hanya bertanya-tanya, apakah kenyamanan tidak menyimpan / melepaskan secara manual (dan mungkin kode yang lebih dapat diandalkan sebagai hasilnya?) Lebih besar daripada 'biaya' menggunakan ARC? Apa pengalaman Anda tentang ARC, dan apakah Anda akan merekomendasikannya?

Begitu:

  • Berapa banyak manfaat yang dapat diberikan ARC untuk sebuah proyek?
  • Apakah ARC memiliki biaya seperti pengumpulan sampah di Jawa?
  • Apakah Anda pernah menggunakan ARC dan jika demikian, bagaimana Anda menemukannya sejauh ini?
Simon Withington
sumber
Tidak ada pengumpulan sampah di ipad / ios. Apakah Anda berbicara tentang OS X?
dasblinkenlight
1
Maafkan saya, saya menggunakan istilah Java yang tidak pada tempatnya. Maksud saya dengan ARC, objek dapat disimpan dalam memori lebih lama dari yang diperlukan, kemudian dilepaskan sebagai grup dalam kumpulan rilis otomatis beberapa waktu kemudian. Ini adalah efek dari mereka yang disimpan dan dilepaskan dengan objek lain nanti, mirip dengan pengumpulan sampah Java yang saya maksud.
Simon Withington
3
@TenementFunster, untuk kode yang sama (tanpa panggilan untuk rilis), ARC akan menahan objek di sekitar tidak lebih dari kode non-ARC. Faktanya, sering kali akan dirilis lebih cepat dari yang Anda inginkan. Ada beberapa hal yang agak lebih lambat, tetapi mereka mempercepat pola umum sedemikian rupa sehingga mengerdilkan dampak kinerja. Untuk banyak pola umum (mempertahankan objek yang dikembalikan dengan autorelease misalnya), Anda benar-benar tidak dapat menulisnya dengan tangan secepat ARC melakukannya secara otomatis.
Rob Napier
1
Berkenaan dengan pengumpulan sampah, lihat jawaban saya untuk pertanyaan serupa ini: Apa perbedaan antara penghitungan referensi otomatis Objective-C dan pengumpulan sampah?
Brad Larson

Jawaban:

147

Tidak ada kerugian. Gunakan. Lakukan hari ini. Ini lebih cepat dari kode lama Anda. Ini lebih aman daripada kode lama Anda. Ini lebih mudah daripada kode lama Anda. Ini bukan pengumpulan sampah. Tidak memiliki overhead waktu proses GC. Kompilator menyisipkan retains dan release di semua tempat yang seharusnya Anda miliki. Tapi itu lebih pintar dari Anda dan dapat mengoptimalkan yang sebenarnya tidak diperlukan (seperti itu dapat membuka loop, menghilangkan variabel sementara, fungsi inline, dll.)

Oke, sekarang saya akan memberi tahu Anda tentang kerugian kecilnya:

  • Jika Anda adalah pengembang ObjC lama, Anda akan bergerak selama sekitar satu minggu ketika Anda melihat kode ARC. Anda akan segera mengatasi ini.

  • Ada beberapa (sangat) komplikasi kecil dalam menghubungkan ke kode Core Foundation. Ada sedikit lebih banyak komplikasi dalam menangani apa pun yang diperlakukan idsebagai a void*. Hal-hal seperti C-array dari iddapat membutuhkan lebih banyak pemikiran untuk dilakukan dengan benar. Penanganan ObjC yang berlebihan va_argsjuga dapat menyebabkan masalah. Kebanyakan hal yang melibatkan matematika pada penunjuk ObjC lebih rumit. Anda seharusnya tidak memiliki banyak hal seperti ini.

  • Anda tidak dapat memasukkan idfile struct. Ini cukup jarang, tetapi terkadang digunakan untuk mengemas data.

  • Jika Anda tidak mengikuti penamaan KVC yang benar, dan Anda mencampurkan kode ARC dan non-ARC, Anda akan mengalami masalah memori. ARC menggunakan penamaan KVC untuk membuat keputusan tentang manajemen memori. Jika itu semua kode ARC, maka tidak masalah karena akan melakukan hal yang sama "salah" di kedua sisi. Tetapi jika itu campuran ARC / non-ARC maka ada ketidakcocokan.

  • ARC akan membocorkan memori selama pengecualian ObjC melempar. Pengecualian ObjC harus sangat dekat dengan penghentian program Anda. Jika Anda menangkap sejumlah besar pengecualian ObjC, Anda salah menggunakannya. Ini dapat diperbaiki menggunakan -fobjc-arc-exceptions, tetapi menimbulkan penalti yang dibahas di bawah ini:

  • ARC tidak akan membocorkan memori selama pengecualian ObjC atau C ++ melontarkan kode ObjC ++, tetapi ini mengorbankan kinerja waktu dan ruang. Ini adalah satu lagi dalam daftar panjang alasan untuk meminimalkan penggunaan ObjC ++.

  • ARC tidak akan berfungsi sama sekali di iPhoneOS 3 atau Mac OS X 10.5 atau versi lebih lama. (Ini menghalangi saya untuk menggunakan ARC di banyak proyek.)

  • __weakpointer tidak berfungsi dengan benar di iOS 4 atau Mac OS X 10.6, yang memalukan, tetapi cukup mudah untuk dikerjakan. __weakpointer memang bagus, tapi itu bukan poin penjualan # 1 dari ARC.

Untuk 95% + kode di luar sana, ARC brilian dan tidak ada alasan sama sekali untuk menghindarinya (asalkan Anda dapat menangani batasan versi OS). Untuk kode non-ARC, Anda dapat meneruskan -fno-objc-arcfile demi file. Xcode sayangnya membuat ini jauh lebih sulit daripada yang seharusnya dilakukan dalam praktiknya. Anda mungkin harus memindahkan kode non-ARC ke xcodeproj terpisah untuk menyederhanakannya.

Kesimpulannya, beralihlah ke ARC sesegera mungkin dan jangan pernah melihat ke belakang.


EDIT

Saya telah melihat beberapa komentar di sepanjang baris "menggunakan ARC bukanlah pengganti untuk mengetahui aturan manajemen memori Cocoa." Ini sebagian besar benar, tetapi penting untuk memahami mengapa dan mengapa tidak. Pertama, jika semua kode Anda menggunakan ARC, dan Anda melanggar Tiga Kata Ajaibdi semua tempat, Anda tetap tidak akan menemui masalah. Mengejutkan untuk dikatakan, tapi begitulah. ARC mungkin menyimpan beberapa hal yang Anda tidak bermaksud untuk menyimpannya, tetapi ARC akan merilisnya juga, jadi itu tidak masalah. Jika saya mengajar kelas baru di Cocoa hari ini, saya mungkin akan menghabiskan tidak lebih dari lima menit pada aturan manajemen memori yang sebenarnya, dan saya mungkin hanya menyebutkan aturan penamaan manajemen memori saat mendiskusikan penamaan KVC. Dengan ARC, saya yakin Anda bisa menjadi pemrogram pemula yang layak tanpa mempelajari aturan manajemen memori sama sekali.

Tetapi Anda tidak bisa menjadi programmer menengah yang layak. Anda perlu mengetahui aturan untuk menjembatani dengan benar dengan Core Foundation, dan setiap programmer perantara perlu berurusan dengan CF di beberapa titik. Dan Anda perlu mengetahui aturan untuk kode campuran-ARC / MRC. Dan Anda perlu mengetahui aturannya saat Anda mulai mengotak-atik void*petunjuk id(yang terus Anda perlukan untuk melakukan KVO dengan benar). Dan memblokir ... yah, manajemen memori blok itu aneh.

Jadi maksud saya adalah bahwa manajemen memori yang mendasarinya masih penting, tetapi di mana saya biasanya menghabiskan waktu yang signifikan untuk menyatakan dan menyatakan kembali aturan untuk programmer baru, dengan ARC itu menjadi topik yang lebih maju. Saya lebih suka membuat pengembang baru berpikir dalam hal grafik objek daripada mengisi kepala mereka dengan panggilan yang mendasarinya objc_retain().

Rob Napier
sumber
3
Satu hal yang harus sangat diperhatikan (di non-ARC juga, tetapi lebih di ARC karena sangat tidak terlihat sekarang) adalah siklus pertahankan. Saran saya di sini adalah 1) jika Anda menyimpan blok objc sebagai variabel instan, perhatikan baik-baik untuk melihat apakah ia dapat menangkap objek yang merupakan ivar, bahkan secara tidak langsung. 2) Sebenarnya desain grafik objek Anda, daripada membiarkannya terjadi. Anda harus tahu apa yang dimiliki jika ingin menulis kode yang baik. 3) Gunakan heapshots: friday.com/bbum/2010/10/17/…
Catfish_Man
1
@Catfishan Semua poin bagus. Mempertahankan loop selalu menjadi masalah. Nasihat baru Apple persis seperti yang Anda katakan di # 2. Kita perlu memikirkan tentang grafik objek daripada mempertahankan dan melepaskan. # 1 adalah masalah serius dengan blok, dan salah satu dari beberapa alasan saya menemukan blok merupakan berkah campuran yang harus didekati dengan hati-hati.
Rob Napier
2
Ada satu kerugian serius yang tidak disebutkan: kompatibilitas silang. Bagi kami orang-orang pemberani dan bodoh yang menghadapi tanah terlantar yang dikenal sebagai pemrograman lintas platform, ARC bukanlah pilihan, setidaknya sampai GNU mengembangkan fitur runtime dan kompiler ObjC mereka lagi (mereka mengatakan lebih banyak sedang dalam perjalanan).
Kelinci
2
Anda dapat menggunakan ARC kecuali Anda perlu mendukung perangkat iOS 3.x. BTW, pastikan untuk menggunakan Xcode untuk melakukan transisi (Edit> Refactor> Convert to Objective-C ARC). Selama proses Xcode akan melakukan banyak validasi untuk memastikan kode Anda akan berfungsi dan mengetahui kode apa pun yang melanggar pedoman perancangan tersebut.
ZhangChn
1
Luar biasa .. jawab dengan tepat. itu yang ke-100 dari saya. Berkumpul selama satu abad;)
Ajay Sharma
20

Lebih baik, jawaban yang lebih teknis akan datang, tapi begini:

  • ARC! = Pengumpulan sampah. Tidak ada penalti run time, itu dilakukan pada waktu kompilasi.
  • ARC juga! = Hanya merilis otomatis semuanya, seperti yang Anda sarankan dalam komentar Anda. Baca dokumennya
  • Ini mengagumkan sekali Anda menyadari betapa manajemen referensi pengguna Anda yang melakukan
  • Gunakan!
  • Satu kelemahan - mempertahankan kode lama, non-arc tiba-tiba menjadi sangat membosankan.
jrturton.dll
sumber
Ya, itulah mengapa saya belum menggunakannya sejauh ini - saya tidak yakin apakah saya dapat menggunakan sejumlah besar kode yang sudah ada sebelumnya untuk mengubahnya ... Saya pasti akan mencobanya pada proyek berikutnya. Terima kasih atas jawaban Anda :)
Simon Withington
Bukan karena mempertahankan kode lama menjadi lebih sulit, itu karena harapan Anda telah berubah. Jadi tidak adil untuk menyalahkan ARC karena membuat hidup lebih mudah. Xcode memudahkan untuk mengonversi kode lama Anda ke ARC saat Anda siap, tetapi Anda jelas tidak dapat menggunakannya jika Anda masih perlu mendukung versi iOS yang lebih lama.
Caleb
1
@Caleb Saya tidak menyalahkan ARC, hanya saja itu satu-satunya kelemahan yang saya lihat sejauh ini - ini memanjakan saya dalam ruang proyek tunggal.
jrturton
Ya; Saya tidak mencantumkannya sebagai masalah, tetapi ada masalah kecil untuk keluar dari praktik manajemen memori ketika Anda harus beralih di antara basis kode. Beberapa proyek saya berjalan di 10.4, jadi saya masih melakukan banyak pekerjaan Objective-C 1.0 (jadi tidak ada @synthesize, apalagi ARC). Tetapi Anda terbiasa beralih mode dengan cukup baik.
Rob Napier
@jrturton Saya seharusnya memperjelas bahwa saya menulis itu untuk kepentingan OP dan pembaca masa depan yang mungkin tidak mengerti apa yang dilakukan ARC. Saya tahu persis apa yang Anda maksud, hanya tidak ingin ada yang menarik kesimpulan yang salah bahwa mencampurkan kode ARC dan non-ARC menciptakan masalah.
Caleb
16

Berapa banyak manfaat yang dapat diberikan ARC untuk sebuah proyek?

Manfaatnya adalah tingkat perlindungan yang signifikan dari kesalahan umum dalam pengelolaan memori. Kebocoran yang disebabkan oleh kegagalan melepaskan objek dan crash karena gagal mempertahankan atau melepaskan objek sebelum waktunya harus dikurangi secara signifikan. Anda masih perlu memahami model memori terhitung referensi sehingga Anda dapat mengklasifikasikan referensi Anda sebagai kuat atau lemah, menghindari siklus penahanan, dan sebagainya.

Berapa sebenarnya 'biaya' untuk pengumpulan sampah?

Tidak ada pengumpulan sampah di iOS. ARC mirip dengan GC karena Anda tidak perlu menyimpan atau melepaskan objek secara manual. Ini tidak seperti GC karena tidak ada pengumpul sampah. Model penahan / rilis masih berlaku, hanya saja kompilator memasukkan panggilan manajemen memori yang sesuai ke dalam kode Anda untuk Anda pada waktu kompilasi.

Apakah Anda pernah menggunakan ARC dan jika demikian, bagaimana Anda menemukannya sejauh ini?

Agak membingungkan jika Anda terbiasa menghitung referensi, tetapi itu hanya masalah membiasakan diri dan belajar untuk percaya bahwa kompilator benar-benar akan melakukan hal yang benar. Rasanya seperti kelanjutan dari perubahan pada properti yang disertakan dengan Objective-C 2.0, yang merupakan langkah besar lainnya untuk menyederhanakan manajemen memori. Tanpa panggilan manajemen memori manual, kode Anda menjadi sedikit lebih pendek dan lebih mudah dibaca.

Satu-satunya masalah dengan ARC adalah bahwa itu tidak didukung di versi iOS yang lebih lama, jadi Anda perlu mempertimbangkannya sebelum Anda memutuskan untuk mengadopsinya.

Caleb
sumber
1
Ada jawaban yang lebih baik yang saya bicarakan!
jrturton
1
Ya, jawaban yang bagus. Jadi apakah benar-benar tidak ada kekurangan ARC selain harus belajar untuk percaya bahwa itu berhasil? Sepertinya terlalu bagus untuk menjadi kenyataan dalam kasus itu?
Simon Withington
4

Menurut saya ARC adalah ide yang bagus. Dibandingkan dengan GC, Anda bisa mendapatkan kue dan memakannya juga. Saya cenderung percaya bahwa MRC menerapkan 'disiplin' yang tak ternilai terhadap manajemen memori yang akan diuntungkan oleh setiap orang. Tapi saya juga setuju bahwa masalah sebenarnya yang harus diperhatikan adalah Kepemilikan Objek dan Grafik Objek (seperti yang telah ditunjukkan banyak orang), dan bukan jumlah referensi tingkat rendah itu sendiri.

Kesimpulannya: ARC BUKANLAH izin untuk tidak memikirkan memori; ini adalah alat untuk membantu manusia menghindari tugas yang berulang, yang menyebabkan stres dan rentan terhadap kesalahan, oleh karena itu lebih baik didelegasikan ke mesin (kompiler, dalam hal ini).

Meskipun demikian, secara pribadi saya adalah pengrajin dan belum melakukan transisi. Saya baru saja mulai menggunakan Git ...

PEMBARUAN: Jadi saya memigrasi seluruh game saya, termasuk perpustakaan gl, dan sejauh ini tidak ada masalah (kecuali dengan asisten migrasi di Xcode 4.2). Jika Anda memulai proyek baru, lakukanlah.

Nicolas Miari
sumber
2

Saya telah menggunakannya dalam beberapa proyek (yang memang kecil), dan saya hanya memiliki pengalaman yang baik, baik dari segi performa maupun keandalan.

Satu catatan kecil yang perlu diperhatikan adalah bahwa Anda perlu mempelajari referensi lemah yang boleh dan tidak boleh dilakukan: agar tidak menyebabkan loop referensi apa pun jika Anda mengkodekan UI Anda sendiri, perancang cenderung melakukannya dengan baik. otomatis jika Anda mengatur GUI Anda menggunakannya.

Joachim Isaksson
sumber
2

Satu-satunya downside yang saya temui adalah jika Anda menggunakan perpustakaan dengan banyak fungsi dan data CoreFoundation. Dalam MRC Anda tidak perlu khawatir tentang menggunakan CFStringRefbukan sebuah NSString*. Di ARC, Anda harus menentukan bagaimana keduanya berinteraksi (jembatan dasar? Lepaskan objek CoreFoundation dan pindahkan ke ARC? Jadikan objek Cocoa sebagai objek yang dipertahankan CoreFoundation +1?) Selain itu, di OS X, ini hanya tersedia di 64- bit code (Meskipun saya memiliki header yang berfungsi untuk itu…).

MaddTheSane
sumber