Yeni otomatik referans sayma mekanizması nasıl çalışır?


206

Birisi bana ARC'nin nasıl çalıştığını kısaca açıklayabilir mi? Garbage Collection'dan farklı olduğunu biliyorum, ama tam olarak nasıl çalıştığını merak ediyordum.

Ayrıca, ARC GC'nin performansı engellemeden yaptığı şeyi yaparsa, Java neden GC'yi kullanır? Neden ARC'yi de kullanmıyor?


2
Bu size her şeyi anlatacak: http://clang.llvm.org/docs/AutomaticReferenceCounting.html Xcode ve iOS 5'de nasıl uygulandığı NDA altında.
Morten Fast

14
@mbehan Bu kötü bir tavsiye. Giriş yapmak ya da iOS geliştirme merkezi için bir hesabım bile olmak istemiyorum, ancak yine de ARC'yi bilmek istiyorum.
Andres F.

1
ARC, GC'nin yaptığı her şeyi yapmaz, güçlü ve zayıf referans semantiği ile açıkça çalışmanızı gerektirir ve bunları doğru şekilde alamazsanız bellek sızdırır. Benim tecrübelerime göre, bu, Objective-C'de blokları kullandığınızda ilk önce zor ve hatta hileler öğrendikten sonra, blokların birçok kullanımının etrafında bazı can sıkıcı (IMO) kazan plakası koduyla kalıyorsunuz. Güçlü / zayıf referansları unutmak daha uygundur. Ayrıca GC, ARC wrt'den biraz daha iyi performans gösterebilir. CPU, ancak daha fazla bellek gerektirir. Çok fazla belleğiniz olduğunda açık bellek yönetiminden daha hızlı olabilir.
TaylanUB

@TaylanUB: "daha fazla bellek gerektirir". Birçok insan bunu söylüyor ama inanmakta zorlanıyorum.
Jon Harrop

2
@JonHarrop: Şu anda neden söylediğimi bile hatırlamıyorum, dürüst olmak gerekirse. :-) Bu arada, bu tür battaniye ifadelerinin muhtemelen değersiz olduğu kadar farklı GC stratejileri olduğunu fark ettim. Hans Boehm'i Bellek Tahsis Mitleri ve Yarı Gerçeklerinden okuyalım : "Bu alan neden şüpheli halk bilgeliğine bu kadar eğilimlidir?"
TaylanUB

Yanıtlar:


244

Objective-C'ye gelen her yeni geliştirici, nesneleri ne zaman tutacağı, serbest bırakacağı ve otomatik serbest bırakma konusundaki katı kuralları öğrenmelidir. Bu kurallar, yöntemlerden döndürülen nesnelerin alıkonma sayısını ima eden adlandırma kurallarını bile belirtir. Objective-C'de bellek yönetimi, bu kuralları kalbe alıp sürekli olarak uyguladıktan sonra ikinci doğa haline gelir, ancak en deneyimli Kakao geliştiricileri bile zaman zaman kaymaktadır.

Clang Statik Analizör ile LLVM geliştiricileri, bu kuralların, kodunuzun aldığı yollarda bellek sızıntılarını ve aşırı yayınları gösterecek bir araç oluşturabilecek kadar güvenilir olduğunu fark etti.

Otomatik referans sayma (ARC) bir sonraki mantıksal adımdır. Derleyici nesneleri nerede tutmanız ve serbest bırakmanız gerektiğini fark edebiliyorsa, neden bu kodu sizin için eklemesin? Katı, tekrarlayan görevler derleyicilerin ve kardeşlerinin mükemmel olduğu şeydir. İnsanlar bir şeyleri unutur ve hatalar yapar, ancak bilgisayarlar çok daha tutarlıdır.

Ancak, bu sizi bu platformlarda bellek yönetimi hakkında endişelenmekten tamamen kurtarmaz. Buradaki cevabımda dikkat edilmesi gereken (döngüleri koruyacak) birincil sorunu açıklıyorum , bu da zayıf işaretçileri işaretlemek için sizin tarafınızdan biraz düşünülmesi gerekebilir. Ancak, bu ARC'de kazandıklarınızla karşılaştırıldığında küçüktür.

Manuel bellek yönetimi ve çöp toplama ile karşılaştırıldığında, ARC, tutma / bırakma kodu yazma ihtiyacını keserek, ancak çöp toplanan bir ortamda görülen durma ve testere dişi bellek profillerine sahip olmayan her iki dünyanın en iyisini sunar. Çöp toplamanın bunun üzerinde sahip olduğu tek avantajlar hakkında tutma döngüleri ve atomik özellik atamalarının ucuz olması ( burada tartışıldığı gibi ). Mevcut tüm Mac GC kodumu ARC uygulamalarıyla değiştirdiğimi biliyorum.

Bunun diğer dillere genişletilip genişletilemeyeceğine ilişkin olarak, Objective-C'deki referans sayma sistemi etrafında düşünülmüş gibi görünüyor. Bunu Java'ya veya diğer dillere uygulamak zor olabilir, ancak orada kesin bir açıklama yapmak için düşük seviyeli derleyici ayrıntıları hakkında yeterince bilgim yok. Apple'ın bu çabayı LLVM'de iten kişi olduğu göz önüne alındığında, başka bir parti buna önemli kaynaklar taahhüt etmedikçe Objective-C önce gelecek.

WWDC'deki bu şok geliştiricilerin tanıtımı, böylece insanlar böyle bir şeyin yapılabileceğinin farkında değildi. Zamanla diğer platformlarda görünebilir, ancak şimdilik LLVM ve Objective-C'ye özeldir.


56
vurgu benim: Bu tamamen bellek yönetimi hakkında endişelenmenize izin vermez
bshirley

6
ARC gerçekten bir yenilik mi? Cevabınızdan, ARC'nin Objective-C'de ilk kez kullanılan yeni bir kavram olduğu sonucuna varıyorum (yanlışsam beni düzeltin). Dürüst olmak gerekirse, bir Objective-C geliştiricisi değilim ve ARC hakkında fazla bir şey bilmiyorum, ancak Boost Shared Pointers (bkz. Boost.org) tam olarak aynı şey değil mi? Ve eğer değillerse, fark nedir?
theDmi

2
@DMM - Aşırı yüklenmiş işleçlere güvenmek yerine (Boost'un yaptığı gibi), bu, onu tüm dile genişleten derleyici düzeyinde bir işlemdir. Diğer şeylerin yanı sıra, manuel olarak referans sayılan bir uygulamayı ARC'ye dönüştürmeyi kolaylaştırır. Boost ayrıca yerel değişkenleri ARC'den farklı şekilde ele alabilir, burada ARC yerel bir değişkenin artık kullanılmadığı anı bilir ve bu noktada serbest bırakabilir. Boost ile, değişkenle işin bittiğini bir şekilde belirtmeniz gerektiğine inanıyorum.
Brad Larson

6
"Yeni mi?" Sorusunu yanıtlamak için Delphi, on yıldan uzun bir süredir dizeler, diziler ve arabirimler (COM desteği için) için otomatik referans sayımına sahiptir. Gc'd ortamıyla "hepsini elle yap" ortamı arasında gerçekten güzel bir uzlaşma olduğunu kabul ediyorum. ObjC ve LLVM'de olduğuna sevindim (diğer diller de bundan yararlanabilir).
davidmw

2
@theDmi: "ARC gerçekten bir yenilik mi?". Otomatik referans sayımı 1960 yılında icat edildi ve Python ve Mathematica gibi birçok dilde kullanıldı. JVM veya CLR'de kullanılmaz, çünkü çok yavaştır ve döngüleri sızdırır.
Jon Harrop

25

ARC, derleyicinin ne zaman alıkoyma / bırakma çağrıldığını anlamasıyla eski tutma / bırakma (MRC) oynar. GC sistemine göre daha yüksek performans, daha düşük bellek kullanımı ve daha öngörülebilir performansa sahip olma eğilimindedir.

Öte yandan, ARC (veya MRC) ile bazı veri yapısı türleri mümkün değildir, ancak GC bunları idare edebilir.

Örnek olarak, düğüm adında bir sınıfınız varsa ve düğümde bir NSArray alt öğesi ve GC ile "sadece çalışan" üst öğeye yönelik tek bir başvuru varsa. ARC (ve manuel referans sayımı) ile bir sorununuz var. Verilen herhangi bir düğüme, alt öğelerinden ve üst öğesinden de başvurulacaktır.

Sevmek:

A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A

A kullanırken her şey yolunda (yerel bir değişken üzerinden söyleyin).

İşiniz bittiğinde (ve B1 / B2 / B3), bir GC sistemi sonunda yığın ve CPU kayıtlarından başlayarak bulabileceği her şeye bakmaya karar verecektir. Asla A, B1, B2, B3'ü bulamaz, böylece onları sonlandırır ve belleği diğer nesnelere geri dönüştürür.

ARC veya MRC kullandığınızda ve A ile bitirdiğinizde 3 yeniden sayımına sahiptir (B1, B2 ve B3 tüm referanslar) ve B1 / B2 / B3'ün referans sayısı 1'dir (A'nın NSArray'ı bir referans tutar her biri). Böylece hiçbir şey onları kullanmasa bile, tüm bu nesneler canlı kalır.

Ortak çözüm, bu referanslardan birinin zayıf olması gerektiğine karar vermektir (referans sayısına katkıda bulunmamak). Bu, bazı kullanım modelleri için işe yarayacaktır, örneğin B1 / B2 / B3'e yalnızca A üzerinden başvurursanız. Ancak diğer modellerde başarısız olur. Örneğin, bazen B1'i basılı tutarsanız ve ana işaretçi aracılığıyla geri tırmanmayı ve A'yı bulmayı beklerseniz, yalnızca B1'i basılı tutarsanız zayıf bir referansla A buharlaşabilir (ve normalde B2) ve B3 alabilir Bununla.

Bazen bu bir sorun değildir, ancak karmaşık veri yapılarıyla çalışmanın bazı yararlı ve doğal yollarının ARC / MRC ile kullanımı çok zordur.

Dolayısıyla ARC, GC'nin hedeflediği aynı sorunları hedefler. Bununla birlikte ARC, GC'den daha sınırlı bir kullanım şekli kümesi üzerinde çalışır, bu nedenle bir GC dili (Java gibi) aldıysanız ve ARC gibi bir şey aşıladıysanız, bazı programlar artık çalışmaz (veya en azından tonlarca terk edilmiş bellek üretecekti) ve ciddi takas sorunlarına neden olabilir veya bellek veya takas alanı tükenebilir).

GC, genel bir çözüm olmaya daha fazla öncelik verirken ARC'nin performansa (veya belki öngörülebilirliğe) daha büyük bir öncelik verdiğini de söyleyebilirsiniz. Sonuç olarak GC, öngörülebilir CPU / bellek taleplerine ve ARC'den daha düşük performansa (normalde) sahiptir, ancak herhangi bir kullanım modelini işleyebilir. ARC, birçok yaygın kullanım modeli için çok daha iyi çalışacaktır, ancak birkaç (geçerli!) Kullanım modeli için düşecek ve ölecektir.


"Öte yandan ARC ile bazı veri yapıları mümkün değil" Sanırım otomatik temizlemenin ipuçları olmadan mümkün olmadığını söylüyorsunuz; açıkçası, veri yapıları.
Steven Fisher

Elbette, ancak SADECE ObjC nesnelerinin otomatik temizlenmesi ARC altında "otomatik temizleme yok" == "temizleme yok". Yine de daha fazla zamanım olduğunda cevap vereceğim.
Stripes

@Stripes: ARC'deki manuel temizlemeye eşdeğer çevrim, örn foo = nil.
Douglas

"[ARC] daha yüksek performansa sahip olacak ... ARC performansa daha fazla öncelik veriyor". Referans sayımın çöp toplama izini takip etmekten çok daha yavaş olduğu iyi bilindiğinde şaşırdım . flyingfrogblog.blogspot.co.uk/2011/01/…
Jon Harrop

2
Teoride GC daha hızlıdır (her bir referans sayısı manipülasyonu çok işlemcili önbellek uyumlu olmalıdır ve birçoğu vardır). Pratikte ObjC için mevcut olan tek GC sistemi çok daha yavaştır. Ayrıca GC sistemlerinin kullanıcı tarafından algılanabilen süreler için iş parçacıklarını rastgele zamanlarda duraklatması da son derece yaygındır (bazı gerçek zamanlı GC sistemleri vardır, ancak bunlar yaygın değildir ve bence "ilginç" kısıtlamaları vardır)
Stripes

4

sihirli

Ancak daha spesifik olarak ARC, kodunuzla tam olarak ne yapacağınızı yaparak çalışır (bazı küçük farklarla). ARC, çalışma zamanı olan ve performansınızı olumsuz yönde etkileyecek olan GC'nin aksine derleme zamanı teknolojisidir. ARC sizin için nesnelere yapılan referansları izleyecek ve tutma / bırakma / otomatik serbest bırakma yöntemlerini normal kurallara göre sentezleyecektir. Bu nedenle ARC, işleri sadece kongre uğruna bir otomatik yayın havuzuna atmak yerine, ihtiyaç duyulmadığı anda serbest bırakabilir.

Diğer bazı iyileştirmeler arasında zayıf referansların sıfırlanması, blokların yığına otomatik olarak kopyalanması, karttaki hızlandırmalar (otomatik kiralama havuzları için 6x!) Yer alır.

Tüm bunların nasıl çalıştığı hakkında daha ayrıntılı tartışma ARC ile ilgili LLVM Dokümanlarında bulunur.


2
-1 "ARC, çalışma zamanı olan ve performansınızı olumsuz etkileyecek olan GC'nin aksine derleme zamanı teknolojisidir". Referans sayımları, çok verimsiz olan çalışma zamanında çarpılır. Bu yüzden JVM ve .NET gibi GC'leri izlemek çok daha hızlı.
Jon Harrop

1
@Jon: Bunun bir kanıtı var mı? Kendi okumamdan, yeni RC algoritmalarının tipik olarak M&S GC'den daha iyi veya daha iyi performans gösterdiği görülüyor.
xryl669

1
@ xryl669: GC El Kitabı'nda ( gchandbook.org ) tam bir açıklama var . Izleme! = M&S olduğunu unutmayın.
Jon Harrop

3

Çöp toplanmasından çok farklıdır. Farklı çizgilere nesne sızdırıyor olabileceğinizi belirten uyarıları gördünüz mü? Bu ifadeler size nesneyi hangi satıra ayırdığınızı bile söyler. Bu bir adım daha ileri götürüldü ve artık uygun yerlere, çoğu programcıdan daha iyi, zamanın neredeyse% 100'üne retain/ releaseifadeleri ekleyebilir . Bazen, yardım etmeniz gereken tutulan nesnelerin bazı garip örnekleri vardır.


0

Apple geliştirici belgeleri tarafından çok iyi açıklanmıştır. "ARC Nasıl Çalışır" bölümünü okuyun

Örneklerin hala ihtiyaç duyulurken yok olmadıklarından emin olmak için ARC, şu anda her sınıf örneğine kaç tane özellik, sabit ve değişken başvurduğunu izler. ARC, söz konusu örneğe en az bir etkin başvuru hâlâ mevcut olduğu sürece bir örneği dağıtmayacaktır.

Örneklerin hala ihtiyaç duyulurken yok olmadıklarından emin olmak için ARC, şu anda her sınıf örneğine kaç tane özellik, sabit ve değişken başvurduğunu izler. ARC, söz konusu örneğe en az bir etkin başvuru hâlâ mevcut olduğu sürece bir örneği dağıtmayacaktır.

Diff'i bilmek. Çöp toplama ve ARC arasında: Bunu okuyun


0

ARC, nesnelerin otomatik bellek yönetimini sağlayan bir derleyici özelliğidir.

Bunun yerine, ne zaman kullanılacağını hatırlamak zorunda kalmazsınız retain, releaseve autoreleaseARC, nesnelerinizin ömür boyu gereksinimlerini değerlendirir ve derleme zamanında sizin için uygun bellek yönetimi çağrılarını otomatik olarak ekler. Derleyici ayrıca sizin için uygun dealloc yöntemleri oluşturur.

Derleyici gerekli retain/releaseçağrıları derleme zamanında ekler , ancak bu çağrılar diğer kodlarda olduğu gibi çalışma zamanında yürütülür.

Aşağıdaki şema size ARC'nin nasıl çalıştığını daha iyi anlayacaktır.

resim açıklamasını buraya girin

İOS geliştirmede yeni olanlar ve Objective C'de iş deneyimi olmayanlar . Bellek yönetimini daha iyi anlamak için lütfen Apple'ın Gelişmiş Bellek Yönetimi Programlama Kılavuzu belgelerine bakın .

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.