ARC'ye mi yoksa ARC'ye mi? Artıları ve eksileri nelerdir? [kapalı]


113

Henüz ARC'yi kullanmadım, çünkü şu anda üzerinde çalıştığım projedeki kodun çoğu iOS 5.0 öncesi yazılmıştı.

Merak ediyordum da, manuel olarak saklamamanın / serbest bırakmanın rahatlığı (ve sonuç olarak gelen daha güvenilir bir kod olabilir mi?) ARC kullanmanın herhangi bir 'maliyetinden' daha mı ağır basıyor? ARC deneyimleriniz nelerdir ve bunu tavsiye eder misiniz?

Yani:

  • ARC bir projeye ne kadar fayda sağlayabilir?
  • ARC'nin Java'da çöp toplama gibi bir maliyeti var mı?
  • ARC kullanıyor muydunuz ve öyleyse, şimdiye kadar nasıl buldunuz?

İpad / ios üzerinde çöp toplama yoktur. OS X hakkında mı konuşuyorsunuz?
dasblinkenlight

1
Özür dilerim, Java terimlerini yerinde kullanıyorum. Demek istediğim, ARC ile nesneler hafızada gerekenden daha uzun süre tutulabilir, daha sonra bir süre sonra otomatik bırakma havuzunda grup olarak serbest bırakılabilir. Bu, bahsettiğim Java'nın çöp toplamasına benzer şekilde, daha sonra diğer nesnelerle birlikte tutulması ve serbest bırakılmasının etkisidir.
Simon Withington

3
@TenementFunster, aynı kod için (serbest bırakma çağrıları hariç), ARC nesneyi ARC olmayan koddan daha uzun süre tutmayacaktır. Aslında, çoğu zaman sizden daha erken yayınlayacaktır. Biraz daha yavaş olan az sayıda şey var, ancak ortak kalıpları o kadar hızlandırdı ki performans etkisini gölgede bırakıyor. Pek çok yaygın model için (örneğin, bir otomatik sürümle döndürülen bir nesneyi korumak), ARC'nin otomatik olarak yapacağı kadar hızlı bir şekilde elle yazamazsınız.
Rob Napier

1
Çöp toplama ile ilgili olarak, bu benzer soruya verdiğim cevaba bakın: Objective-C otomatik referans sayımı ile çöp toplama arasındaki fark nedir?
Brad Larson

Yanıtlar:


147

Olumsuz tarafı yok. Kullan onu. Bugün yap. Eski kodunuzdan daha hızlıdır. Eski kodunuzdan daha güvenlidir. Eski kodunuzdan daha kolaydır. Çöp toplama değildir. GC çalışma zamanı ek yükü yoktur. Derleyici ekler, sahip olmanız gereken her yerde saklar ve yayınlar. Ancak sizden daha akıllıdır ve gerçekte ihtiyaç duyulmayanları optimize edebilir (tıpkı döngüleri açabilmesi, geçici değişkenleri ortadan kaldırması, satır içi işlevler vb. Gibi)

Tamam, şimdi size küçük olumsuzluklardan bahsedeceğim:

  • Uzun süredir ObjC geliştiriciyseniz, ARC kodunu gördüğünüzde yaklaşık bir hafta boyunca seğireceksiniz. Bunu çok çabuk aşacaksın.

  • Core Foundation koduna köprü oluşturmanın bazı (çok) küçük komplikasyonları vardır. "A" idolarak kabul edilen herhangi bir şeyle uğraşırken biraz daha fazla karmaşıklık vardır void*. C dizileri gibi şeylerin iddoğru yapılması için biraz daha düşünmek gerekebilir. ObjC'nin süslü kullanımı va_argsda soruna neden olabilir. Bir ObjC işaretçisinde matematikle ilgili çoğu şey daha yanıltıcıdır. Her halükarda bundan fazlasına sahip olmamalısın.

  • Bir koyamazsınız idbir yer struct. Bu oldukça nadirdir, ancak bazen verileri paketlemek için kullanılır.

  • Doğru KVC isimlendirmesini takip etmediyseniz ve ARC ile ARC olmayan kodu karıştırırsanız, hafıza problemleriniz olacaktır. ARC, bellek yönetimi hakkında kararlar almak için KVC adlandırmasını kullanır. Hepsi ARC koduysa, o zaman önemli değil çünkü her iki tarafta da aynı "yanlış" yapacaktır. Ancak karışık ARC / ARC olmayan ise, o zaman bir uyumsuzluk vardır.

  • ARC, ObjC istisna atışları sırasında bellek sızdırır. Bir ObjC istisnası, programınızın sonlandırılmasına çok yakın olmalıdır. Önemli sayıda ObjC istisnası yakalıyorsanız, bunları yanlış kullanıyorsunuz demektir. Bu, kullanılarak düzeltilebilir -fobjc-arc-exceptions, ancak aşağıda tartışılan cezalara tabidir:

  • ARC, ObjC ++ kodunda ObjC veya C ++ istisnası atışları sırasında bellek sızdırmaz, ancak bu hem zaman hem de alan performansı pahasına olur. Bu, ObjC ++ kullanımınızı en aza indirmek için uzun bir nedenler listesinde bir diğeridir.

  • ARC, iPhoneOS 3 veya Mac OS X 10.5 veya önceki sürümlerde hiç çalışmayacaktır. (Bu, birçok projede ARC kullanmamı engelliyor.)

  • __weakişaretçiler iOS 4 veya Mac OS X 10.6'da düzgün çalışmıyor, bu utanç verici, ancak üzerinde çalışılması oldukça kolay. __weakişaretçiler harika, ancak ARC'nin 1 numaralı satış noktası değiller.

% 95'ten fazla kod için, ARC mükemmeldir ve bundan kaçınmak için hiçbir neden yoktur (işletim sistemi sürüm kısıtlamalarını kaldırabilmeniz koşuluyla). ARC dışı kod için, -fno-objc-arcdosya bazında aktarabilirsiniz. Xcode maalesef bunu pratikte yapması gerekenden çok daha zor hale getiriyor. Bunu basitleştirmek için muhtemelen ARC olmayan kodu ayrı bir xcodeproj'a taşımalısınız.

Sonuç olarak, mümkün olan en kısa sürede ARC'ye geçin ve asla geriye bakmayın.


DÜZENLE

"ARC kullanmak, Cocoa bellek yönetimi kurallarını bilmenin yerini tutmaz" şeklinde birkaç yorum gördüm. Bu çoğunlukla doğrudur, ancak nedenini ve neden olmadığını anlamak önemlidir. İlk olarak, kodunuzun tamamı ARC kullanıyorsa ve Üç Sihirli Kelimeyi ihlal ediyorsanızher yerde, yine de sorun yaşamayacaksınız. Söylemesi şok edici, ama buyrun. ARC, saklamasını istemediğiniz bazı şeyleri saklayabilir, ancak onları da serbest bırakır, böylece asla önemi olmaz. Bugün Cocoa'da yeni bir sınıf öğretiyor olsaydım, gerçek bellek yönetimi kurallarına muhtemelen beş dakikadan fazla zaman harcamazdım ve muhtemelen KVC isimlendirmesini tartışırken sadece bellek yönetimi adlandırma kurallarından söz ederdim. ARC ile, bellek yönetimi kurallarını hiç öğrenmeden iyi bir başlangıç ​​programcısı olabileceğine inanıyorum.

Ama iyi bir ara programcı olamazsın. Core Foundation ile doğru bir şekilde köprü kurmak için kuralları bilmeniz gerekir ve her ara programcının bir noktada CF ile ilgilenmesi gerekir. Ve karışık ARC / MRC kodu için kuralları bilmeniz gerekir. Ve void*işaretçilerle iduğraşmaya başladığınızda kuralları bilmeniz gerekir (KVO'yu doğru şekilde gerçekleştirmeye devam etmeniz gerekir). Ve bloklar ... pekala, blok bellek yönetimi çok garip.

Demek istediğim, temel bellek yönetiminin hala önemli olduğu, ancak yeni programcılar için kuralları belirtmek ve yeniden düzenlemek için önemli ölçüde zaman harcadığım yerlerde, ARC ile daha ileri bir konu haline geliyor. Yeni geliştiricilerin kafalarını temel çağrılarla doldurmak yerine nesne grafikleri açısından düşünmelerini tercih ederim objc_retain().


3
Çok dikkatli olunması gereken bir şey (ARC olmayanlarda da, ancak ARC'de daha fazlası çünkü şu anda çok görünmez) koruma döngüleri. Buradaki tavsiyem 1) eğer kendinizi bir nesne değişkeni olarak bir nesne bloğunu saklarken bulursanız, dolaylı olarak bile olsa bir nesneyi yakalayıp yakalayamayacağını görmek için ona uzun süre dikkatlice bakın. 2) Sadece olmasına izin vermek yerine, aslında nesne grafiğinizi tasarlayın. Sen gerekir Eğer iyi kod yazmak isterseniz işin sahibi biliyorum. 3) Yığın görüntülerini kullanın: friday.com/bbum/2010/10/17/…
Catfish_Man

1
@Catfish_Man Tüm iyi noktalar. Tutma döngüleri her zaman bir sorun olmuştur. Apple'ın yeni tavsiyesi tam olarak 2. maddede söylediğiniz gibi. Saklamak ve serbest bırakmak yerine nesne grafikleri hakkında düşünmemiz gerekiyor. # 1, bloklarla ilgili ciddi bir sorundur ve bloklara dikkatle yaklaşılması gereken karışık bir lütuf bulmamın birkaç nedeninden biri.
Rob Napier

2
Bahsedilmeyen ciddi bir dezavantaj var: çapraz uyumluluk. Platformlar arası programlama olarak bilinen çorak arazilerle yüzleşen biz cesur ve aptal ruhlar için ARC, en azından GNU, ObjC çalışma zamanını ve derleyici özelliklerini tekrar genişletene kadar (daha fazlasının yolda olduğunu söylerler) sadece bir seçenek değildir.
Tavşan

2
ARC'yi kullanabilirsiniz, ancak iOS 3.x cihazlarını desteklemeniz gerekir. BTW, geçişi yapmak için Xcode kullandığınızdan emin olun (Düzen> Yeniden Düzenleme> Objective-C ARC'ye Dönüştür). İşlem sırasında Xcode, kodunuzun çalıştığından emin olmak ve bu tasarım yönergelerini ihlal eden herhangi bir kodu bulmak için çok fazla doğrulama yapacaktır.
ZhangChn

1
Mükemmel .. noktasal cevap. bu benden 100. Bir asırdır tebrikler;)
Ajay Sharma

20

Daha iyi, benimkinden daha teknik cevaplar gelecek, ama işte burada:

  • ARC! = Çöp toplama. Çalışma süresi cezası yoktur, derleme zamanında yapılır.
  • ARC ayrıca! = Yorumunuzda önerdiğiniz gibi sadece her şeyi otomatik olarak yayınlar. Belgeleri okuyun
  • Bu size ne kadar manuel referans yönetimini gerçekleştirmek kez müthiş edildi yapıyor
  • Kullan onu!
  • Bir dezavantaj - eski, ark olmayan kodu korumak aniden çok sıkıcı hale gelir.

Evet, bu yüzden şimdiye kadar kullanmadım - onu dönüştürmek için önemli miktarda önceden var olan kodumuzu gözden geçirmeye dayanamayacağımdan emin değilim ... Yine de bir sonraki projede kesinlikle deneyeceğim. Cevabınız için teşekkürler :)
Simon Withington

Eski kodu korumanın daha zor hale gelmesi değil, beklentinizin değişmesi. Bu nedenle, hayatı kolaylaştırmak için ARC'yi suçlamak pek adil değil. Xcode, hazır olduğunuzda eski kodunuzu ARC'ye dönüştürmeyi kolaylaştırır, ancak hala eski iOS sürümlerini desteklemeniz gerekiyorsa onu kullanamazsınız.
Caleb

1
@Caleb ARC'yi suçlamıyordum, şu ana kadar gördüğüm tek dezavantajı bu - tek bir proje alanında beni çürüttü.
jrturton

Evet; Bunu bir sorun olarak listelemedim, ancak kod tabanları arasında geçiş yapmanız gerektiğinde bellek yönetimi uygulamasından çıkmanın küçük bir sorunu var. Projelerimden bazıları 10.4'te çalışıyor, bu yüzden hala çok sayıda Objective-C 1.0 çalışması yapıyorum (yani @ sentezleme, ARC'yi bırakın). Ancak mod değiştirmeye oldukça iyi alışırsınız.
Rob Napier

@jrturton Bunu OP'nin ve ARC'nin yaptıklarını alay etmeyen gelecekteki okuyucuların yararına yazdığımı daha net belirtmeliydim. Ne demek istediğini tam olarak anlıyorum, sadece kimsenin ARC ve ARC olmayan kodların karıştırılmasının bir sorun yarattığı yanlış sonucuna varmasını istemedim.
Caleb

16

ARC bir projeye ne kadar fayda sağlayabilir?

Bunun faydası, yaygın bellek yönetimi hatalarından önemli derecede korumadır. Bir nesnenin serbest bırakılamamasından kaynaklanan sızıntılar ve bir nesnenin tutulamaması veya erken bırakılmasından kaynaklanan çökmeler önemli ölçüde azaltılmalıdır. Referans sayılan bellek modelini yine de anlamanız gerekir, böylece referanslarınızı güçlü veya zayıf olarak sınıflandırabilir, döngüleri engellemekten kaçınabilir, vb.

Çöp toplamanın gerçekten 'maliyeti' nedir?

İOS'ta çöp toplama yoktur. ARC, nesneleri manuel olarak saklamanız veya bırakmanız gerekmediği için GC'ye benzer. Çöp toplayıcı olmaması GC'den farklıdır. Saklama / yayınlama modeli hala geçerlidir, sadece derleyici uygun bellek yönetimi çağrılarını sizin için derleme zamanında kodunuza ekler.

ARC kullanıyor muydunuz ve öyleyse, şimdiye kadar nasıl buldunuz?

Saymaya alışkınsanız bu biraz endişe vericidir, ancak bu sadece buna alışmak ve derleyicinin gerçekten doğru şeyi yapacağına güvenmeyi öğrenmek meselesidir. Bellek yönetimini basitleştirmeye yönelik bir başka büyük adım olan Objective-C 2.0 ile gelen özelliklerde yapılan değişikliğin bir devamı gibi geliyor. Manuel bellek yönetimi çağrıları olmadan, kodunuz biraz kısalır ve okunması daha kolay hale gelir.

ARC ile ilgili tek sorun, iOS'un eski sürümlerinde desteklenmemesidir, bu nedenle onu benimsemeye karar vermeden önce bunu dikkate almanız gerekir.


1
Bahsettiğim daha iyi cevap var!
Jrturton

1
Evet, harika cevap. Öyleyse ARC'nin işe yaradığına güvenmeyi öğrenmek zorunda kalmanın dışında gerçekten bir sakıncası yok mu? Bu durumda gerçek olamayacak kadar iyi görünüyor?
Simon Withington

4

ARC'nin harika bir fikir olduğunu düşünüyorum. GC'ye kıyasla pastanızı alabilir ve yiyebilirsiniz. MRC'nin bellek yönetimine karşı herkesin sahip olmasından fayda sağlayacağı paha biçilmez bir 'disiplin' dayattığına inanma eğilimindeyim. Ama aynı zamanda farkında olunması gereken asıl sorunun Nesne Sahipliği ve Nesne Grafikleri (çoğunun işaret ettiği gibi) olduğunu ve kendi başına düşük seviyeli referans sayıları olmadığını kabul ediyorum.

Sonuç olarak: ARC, bellek konusunda bilinçsiz olmak için ücretsiz bir geçiş DEĞİLDİR; İnsanların strese neden olan ve hataya yatkın olan tekrarlayan görevlerden kaçınmasına yardımcı olan bir araçtır, bu nedenle bir makineye (bu durumda derleyiciye) daha iyi atanır.

Bununla birlikte, ben şahsen bir tür zanaatkarım ve henüz geçiş yapmadım. Git kullanmaya yeni başladım ...

GÜNCELLEME: Bu yüzden tüm oyunumu taşıdım, gl kitaplığı dahil ve şu ana kadar hiçbir sorun yaşamadım (Xcode 4.2'deki taşıma asistanı hariç). Yeni bir projeye başlıyorsanız, devam edin.


2

Bunu birkaç (kuşkusuz küçük) projede kullandım ve hem performans hem de güvenilirlik açısından yalnızca iyi deneyimlerim var.

Küçük bir uyarı notu, kullanıcı arayüzünüzü kendiniz kodluyorsanız, herhangi bir referans döngüsüne neden olmamak için zayıf referansların do: s ve don't: s'lerini öğrenmeniz gerektiğidir, tasarımcı bunu iyi bir şekilde yapma eğilimindedir. GUI'nizi kullanarak kurarsanız otomatik olarak.


2

Karşılaştığım tek dezavantaj, çok sayıda CoreFoundation işlevi ve verisi içeren bir kitaplık kullanıyorsanız. MRC'de bir CFStringRefyerine a kullanma konusunda endişelenmenize gerek yoktu NSString*. ARC'de, ikisinin nasıl etkileşime girdiğini belirlemeniz gerekir (temel köprü? CoreFoundation nesnesini serbest bırakıp ARC'ye taşıyın? Bir Cocoa nesnesini +1 CoreFoundation tutulan nesne olarak yapın?) Ayrıca, OS X'te, yalnızca 64- bit kodu (bunun etrafında çalışan bir başlığım olmasına rağmen…).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.