|
|
|
|
|
by gchpaco
4129 days ago
|
|
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)). |
|
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.)