5

There are a plenty of questions on SO regarding objective c ARC mechanism. Many people asking if ARC is going to replace GC or not, etc. There are even discussions whether it's reasonable to move to ARC from GC for Mac apps(if that does not require much work handling complex references in some data types, etc).

The obvious disadvantage of ARC is complete lack of any mechanism for cleaning cyclic references (edit: cyclic strong references). Here's a very good and simple explanation on memory leaks with ARC What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

And interesting overview of advantages of apple's ARC over their GC. http://lists.apple.com/archives/objc-language/2011/Jun/msg00013.html

I have a good understanding on how GC works and what kind of problems it has, but moving from C#/.NET world to objective c / Cocoa and reading stuff about ARC I still cannot get one simple thing - why there is no background mechanism to clean cyclic references in ARC application.

It does not require threads suspending, does it? So is relatively cheap to have. Is it a problem to implement one? An light version of GC which scans stack, registers, builds graph, finds cyclic references and frees memory without suspending application threads, sounds cool, no?

Does it require serious computation or other resources? It's hard for me to imagine how to find cyclic references without building all the object graph, but assuming this process is background and continuous it should be ok even in that way?

.NET 4.5 GC (http://blogs.msdn.com/b/dotnet/archive/2012/07/20/the-net-framework-4-5-includes-new-garbage-collector-enhancements-for-client-and-server-apps.aspx) has serious improvements in performance, but having cyclic references collector in ARC system will make second a winner? What are the next steps of ARC system evolution? If it's possible and will sometime happen ARC will have cyclic references collector, can it then fully replace GC, or next gen GCs (with even better performance) are going to eliminate ARC systems?

UPD: Please do not post about weak references, I know how to deal with cyclic references in ARC, and that's obvious, the question is about possibility to add cyclic references collector to existing ARC mechanism, as it would be as powerful and generic as modern GC are

Community
  • 1
  • 1
illegal-immigrant
  • 8,089
  • 9
  • 51
  • 84
  • Maybe it's just a matter of efficiency. After all we know how to break strong reference cycles: we just set all the linked references to nil. – Ramy Al Zuhouri Dec 13 '12 at 16:58
  • As for the ObjC - if there is a cyclic reference then you probably have design issues and need to review an architecture of your app. I've never experienced problems where such cycles were unavoidable. – Max Dec 13 '12 at 17:00
  • 1
    Max, I would like to see how you avoid cyclic references in Circular buffer or say graph containing all the cities and roads in a traveling salesman problem... – illegal-immigrant Dec 13 '12 at 17:09
  • Your cyclic reference point is not directly related with the ARC. It's not a important point when to choose between GC , ARC, or old school manual RC. – 9dan Dec 13 '12 at 17:18
  • 1
    Why not? It's a major disadvantage of ARC compared to GC – illegal-immigrant Dec 13 '12 at 17:20
  • 3
    Keep an nsarray or nsdictionary with strong pointers to all the nodes in the graph, and use weak pointers internally in the graph. Weak pointers are the mechanism in ARC for resolving cyclic reference issues. (and they rock). – Minthos Dec 13 '12 at 17:22
  • 1
    For me the main advantage of ARC or manual memory management over GC is determinism, i.e. I know exactly where and when my objects are destroyed. – Max Dec 13 '12 at 17:24
  • 1
    @taras, Major advantage of ref. counting are better performance(hopefully), better determinism, optimal memory foot print, and so on. And ARC is Automatic! – 9dan Dec 13 '12 at 17:24
  • Yes, and adding cyclic references collecting mechanism to ARC would even make ARC GENERIC solution, as modern GC are. So it will be fast, deterministic and efficient, with almost no cons. And that's the question - if it's possible and reasonable to add such mechanism to ARC system – illegal-immigrant Dec 13 '12 at 17:48
  • 1
    @taras.roshko Adding cyclic detection/collection would either make it indeterministic or _extremely_ slow. Since most if not all cyclic graphs can be solved in other ways using `weak` ARC (an example of which Minthos gave above), why add the complexity? – Joachim Isaksson Dec 13 '12 at 18:06
  • @JoachimIsaksson collecting cycles will be indeterministic, yes, but other deallocs will remain the same, deterministic. Why it should be slow? You run background thread, it builds object graph and without any suspends of threads can free memory consumed by cycle references. – illegal-immigrant Dec 13 '12 at 18:11
  • There is a tremendous amount of overhead in a "powerful and generic modern GC". Especially when it is on top of a VM. And it is all tradeoffs. For example, a JIT compiler may offer extraordinary speed, but it comes at the cost of a huge memory hit in that you can't share as much (if any -- security, natch) code between processes. – bbum Dec 13 '12 at 20:27
  • @Max: "For me the main advantage of ARC or manual memory management over GC is determinism, i.e. I know exactly where and when my objects are destroyed". Ironically, ARC is non-deterministic. – J D Jan 26 '14 at 12:29
  • @9dan: "Major advantage of ref. counting are better performance(hopefully), better determinism, optimal memory foot print". Let me debunk some of those common myths for you: http://flyingfrogblog.blogspot.co.uk/2011/01/boosts-sharedptr-up-to-10-slower-than.html http://flyingfrogblog.blogspot.co.uk/2013/10/memory-management-myths-promptness.html http://flyingfrogblog.blogspot.co.uk/2013/10/thread-safe-reference-counting-is-not.html – J D Jan 26 '14 at 12:33

2 Answers2

8

Cycle detection in a C based world requires one of two things:

  • all assignments of objects everywhere always go through a write barrier (and, potentially, a read barrier, depending on the features of the collector)

  • the scanner must "stop the world" to hold memory in a consistent state when scanning for cycles

The former is a unified memory model and incurs massive overhead compared to straight C (but can be made more efficient than pure manual retain/release). In practice, you typically would "escape" objects from the barrier'd world into un-barrier'd locations using some kind of manual reference count (which is pretty much identical to the bridging mechanisms in the ARC compiler; CFBridgingRetain(), etc...)

The latter is much easier on the developer, but makes performance completely unpredictable as you can never know when, or for how long, any given thread is going to stop. Without barriers, you can't really stop only one thread at a time.

Both of these add significant overhead compared to the relative "at the metal" nature of a C based environment. In a VM based environment, the cost is largely addressed by a combination of the virtualization of the object graph connectivity combined with execution path following JIT compilation that achieves optimizations well beyond what is possible in a pre-compiled environment like C (precompiled, static executables... not the precompiler itself).

bbum
  • 162,346
  • 23
  • 271
  • 359
  • Nice answer, however I would ask you for some further reading on first approach, could you please suggest some articles? – illegal-immigrant Dec 17 '12 at 12:57
  • See the implementation of the Objective-C GC. It is open source. The compiler was modified to emit write barriers in GC compiled code while the compiler/collector colluded via write barriers to know when an object pointer escaped GC managed memory (or stack memory -- different, very fast, optimization). Over-simplification. – bbum Dec 17 '12 at 16:55
0

Your question should have been: What is the mechanism to resolve cyclic reference issues in ARC?

And to that, the answer is: Weak pointers.

Minthos
  • 900
  • 4
  • 13
  • Have you really read my question? I guess no, because it's about possibility to add cyclic references collection to existing ARC mechanism and how that would compare to GC then in terms of generic memory management mechanism. – illegal-immigrant Dec 13 '12 at 17:42
  • Yes I read your question. And it appears to be based on the assumption that ARC has no mechanism to deal with cyclic references, which it does. – Minthos Dec 13 '12 at 18:02
  • And where have you found such assumption? First link in question points to answer with weak references, so yes, I do known how to deal with cyclic references, and the main message is selected using BOLD. Please point me to invalid assumptions in my question and I will edit it – illegal-immigrant Dec 13 '12 at 18:06
  • Your words: "The obvious disadvantage of ARC is complete lack of any mechanism for cleaning cyclic references." – Minthos Dec 13 '12 at 18:23
  • Thank you, I will correct it asap, I wanted to point to strong cycle references. Yes, that was probably misunderstanding – illegal-immigrant Dec 13 '12 at 18:36