Hacker News new | ask | show | jobs
by jeffsco 4129 days ago
What Apple calls "automatic reference counting" is what is usually known as just "reference counting." They call it "automatic" to distinguish it from the previous, even cruder, system where counts were manipulated directly by the programmer. Obviously this is an improvement, but personally I am a supporter of GC. It is a myth that reference counting is not subject to arbitrary pauses: http://www.hboehm.info/gc/myths.ps
1 comments

Incorrect.

You can, although I haven't seen systems that do this, enqueue objects to be deallocated then have either the main thread every once in a while or a background thread periodically pop objects off of the queue and do the normal reference counting dance.

Yup, the problem with this is that it renders the other claimed advantage of reference counting moot (viz. there is now little or no temporal linkage between when the object's ref count hits 0 and when its destructor/finalizer is called).

The other problem with reference counting, which is I believe insoluble, is that it is inherently O(alldata); that is to say you must perform an operation each time a piece of memory dies, at the very least. This makes it good for collecting older generations in a generational GC (where O(alldata) ~= O(livedata)) but bad for the nursery (where the generational assumption means that O(livedata) << O(alldata)).

Any computer processor can do a finite number of operations per time period, and an (effectively) arbitrary number of objects can be marked for deallocation simultaneously. So yes, you can have arbitrary delays.

But this is always the case. Refcounting, GC, manual memory management, etc. But I'd say you've gone one step too far in saying that there is little or no temporal linkage with refcounting. If you're using a queue, objects will be cleaned up as soon as they can be while remaining inside the time limitations you've allowed.

If you want to get fancy, you can even have the compiler rearrange objects such that pointers that are likely to point to objects with destructors are first in line.

And yes, refcounting is O(alldata). But that's ignoring that freeing is relatively fast, and that you can easily implement bunches and bunches of optimizations to prevent refcounting from having to work at all.(For example: if you acquire a reference to an object on the same thread and then release it, you don't have to do anything. If you create an object, but at runtime you can determine that you never released the reference to anything, you can free it immediately. If you acquire multiple references to an object, you only need to check for references reaching zero once. Etc. All of these are things that theoretically can be done with a standard GC, but good luck actually doing so.)

So in the end you implement a poor man's GC.
Reference counting is GC - or rather it solves the same problem that GC solves. I don't see why people don't count it as one. Sure, basic reference counting cannot handle cycles - but there are extensions that can.
Sure it is GC, the very first chapter in most CS books about automatic memory management starts with reference counting and then proceed to more elaborate algorithms.

It is usually presented as a quick solution for when the resources for doing more powerful GC algorithms aren't available, either in computing power or engineering.

Also, a minor addition to my previous comment.

Yes, with reference counting you must perform operations per allocation. But you already need to do this. Malloc / free, even arena-based solutions, all do this.

This is pretty much what the perl5 VM does on scope exit to blow away unused temporaries.

Weak references take a while to figure out but once you have, refcounting is so much more predictable than GC.