12

If you were designing a programming language that features automatic memory management, would using reference counting allow for determinism guarantees that are not possible with a garbage collector?

Would there be a different answer to this question for functional vs. imperative languages?

lornova
  • 6,667
  • 9
  • 47
  • 74
Steve
  • 8,153
  • 9
  • 44
  • 91

6 Answers6

18

Would using reference counting allow for determinism guarantees that are not possible with a garbage collector?

The word guarantee is a strong one. Here are the guarantees you can provide with reference counting:

  • Constant time overhead at an assignment to adjust reference counts.

  • Constant time to free an object whose reference count goes to zero. (The key is that you must not decrement that object's children right away; instead you must do it lazily when the object is used to satisfy a future allocation request.)

  • Constant time to allocate a new object when the relevant free list is not empty. This guarantee is conditional and isn't worth much.

Here are some things you can't guarantee with reference counting:

  • Constant time to allocate a new object. (In the worst case, the heap may be growing, and depending on the system the delay to organize new memory may be considerable. Or even worse, you may fill the heap and be unable to allocate.)

  • All unreachable objects are reclaimed and reused while maintaining constant time for other operations. (A standard reference counter can't collect cyclic garbage. There are a variety of ingenious workarounds, but generally they invalidate constant-time guarantees for simple operations.)

There are now some real-time garbage collectors that provide pretty interesting guarantees about pause times, and in the last 5 years there have been pretty interesting developments in both reference counting and garbage collection. From where I sit as an informed outsider, there's no obvious winner.

Some of the best recent work on reference counting is by David Bacon of IBM and by Erez Petrank of Technion. If you want to learn what a sophisticated, modern reference-counting system can do, look up their papers. Among other things, they are using multiple processors in amazing ways.

For information about memory management and real-time guarantees more generally, check out the International Symposium on Memory Management.

Would there be a different answer to this question for functional vs. imperative languages?

Because you asked about guarantees, no. But for memory management in general, the performance tradeoffs are quite different for an imperative language (lots of mutation but low allocation rates), an impure functional language (hardly any mutation but high allocation rates), and a pure, lazy functional language (lots of mutation—all those thinks being updated—and high allocation rates).

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 2
    "All unreachable objects are reclaimed and reused while maintaining constant time for other operations". Given that the question is about creating a new language you could just choose to enforce a unidirectional heap (e.g. as Erlang and Mathematica do) so you can guarantee that all unreachable objects are reclaimed and reused while maintaining constant time for other operations. – J D Jul 08 '12 at 18:33
  • It's possible to implement hard real time reference counting(at a price): see "Reference counting for hard real time systems" , by T Ritzau – Alex Brooks Jul 20 '13 at 14:18
8

would using reference counting allow for determinism guarantees that are not possible with a garbage collector?

I don't see how. The process of lowering the reference count of an object is not time-bounded, as that object may be the single root for an arbitrary large object graph.

The only way to approach the problem of GC for real-time systems is by using either a concurrent collector or an incremental one - and no matter if the system uses reference counting or not; in my opinion your distinction between reference counting and "collection" is not precise anyway, e.g. systems which utilize reference counting might still occasionally perform some memory sweep (for example, to handle cycles).

You might be interested in IBM's Metronome, and I also know Microsoft has done some research in direction of good, real-time memory management.

Oak
  • 26,231
  • 8
  • 93
  • 152
4

If you look at the RTSJ spec (JSR-1), you'll see they did an end-run around the problem by providing for no-heap realtime threads. By having a separate category of thread that isn't allowed to touch any object that might require the thread to be stopped for garbage collection, JSR-1 side stepped the issue. There aren't many RTSJ implementations right now, but the area of realtime garbage collection is a hot topic in that community.

JustJeff
  • 12,640
  • 5
  • 49
  • 63
  • By "touch" do you mean "write", or "write anything other than primitive fields", or "examine in any way"? Or is there some kind of non-heap indexed storage that both real-time and non-real-time threads can access? I wouldn't think real-time threads would be very useful if they were limited to reading and writing fixed-sized primitives, but I can imagine many mechanisms via which things like arrays could usefully be allowed. – supercat Jan 26 '13 at 20:28
  • @supercat - of course I haven't touched rtsj in a few years so I may well be off in this, but here goes - by 'touch' I believe I meant 'access'. Basically heap objects are forbidden to NHRT threads. What you *can* access with NHRT threads are objects allocated out of 'immortal memory' or (I think) 'scoped' memory. RTSJ kind of made memory in Java kind of complicated, relative to the non RTSJ. – JustJeff Feb 09 '13 at 00:04
2

For real time programming, does reference counting have an advantage over garbage collection in terms of determinism?

Yes. The main advantage of reference counting is simplicity.

If you were designing a programming language that features automatic memory management, would using reference counting allow for determinism guarantees that are not possible with a garbage collector?

A GC like Baker's Treadmill should attain the same level of guarantees regarding determinism that reference counting offers.

Would there be a different answer to this question for functional vs. imperative languages?

Yes. Reference counting alone does not handle cycles. Some functional languages make it impossible to create cycles by design (e.g. Erlang and Mathematica) so they trivially permit reference counting alone as an exact approach to GC.

J D
  • 48,105
  • 13
  • 171
  • 274
1

In real time programming garbage collection could be harmful, because you don't know when the garbage collector will collect... so yes, reference counting is definitely better in this context.

As a side note, usually in real time system only some parts needs real time processing, so you could avoid garbage collection just in sensitive components. A real world example is a C# program running on a Windows CE target.

lornova
  • 6,667
  • 9
  • 47
  • 74
  • There are ways of implementing garbage-collection so as not to require "stop the world" behavior. These generally require that garbage collection be triggered while there is still enough space available to satisfy any requests that may arrive before garbage-collection completes, and they also impair performance to some extent even when garbage-collection is not in progress, but a concurrent compacting garbage-collector may be superior to a non-compacting reference-count-based system in some real-time scenarios. – supercat Mar 28 '11 at 16:13
  • For example, a system might require that every time an object reference is stored someplace and the target isn't marked as "live", it must be added to a list of new live objects; the "mark" phase of the GC would initialize the list to point to all rooted objects, and then go through the list and add to the list every nested item that isn't already marked as "live". Once the list is empty, the "sweep" phase could relocate each object that wasn't marked "live", pausing any time it would move an object that was being actively dereferenced. – supercat Mar 28 '11 at 16:21
0

From some involvement in various projects migrating significant chunks of code from C++ (with various smart pointer classes, including reference counted) to garbage collected Java/C#, I observe that the biggest pain-points all seem to be related to classes with non-empty destructors (particularly when used for RAII). This is a pretty big flag that deterministic cleanup is expected.

The issue is surely much the same for any language with objects; I don't think hybrid OO-functional languages like Scala or Ocaml enjoy any particular advantages in this area. Situation might be different for more "pure" functional languages.

timday
  • 24,582
  • 12
  • 83
  • 135
  • 1
    -1 Deterministic cleanup is easily done in any functional language and it has nothing to do with real time. – J D Jul 08 '12 at 18:41