The myth of C++ efficiency (reaffirmed! :-)
Author |
Message |
Ulrich Win #46 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
Quote:
> > With the STL and a reference-counting genericized smart-pointer at > > hand, GC is not necessary at all. In terms of efficiency, I would > > guess access is at least on par with Eiffel's object ref's.
Try manipulationg complex, dynamic, and circular graph structures. I think you will have either have to spend a lot of time calling your destructors and determining which destructors to call. Call them once, but not twice! Quote: > Very surprising opinion. With tracing type of GCs, accessing an > object is just a pointer dereference and no special operation is > needed when passing object refs. Smart pointer schemes require an > indirection on accessing objects and expensive arithmetics on > duplicating references.
Ulrich Windl
|
Mon, 12 Oct 1998 03:00:00 GMT |
|
|
Mike Youn #47 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
Quote:
> > > With the STL and a reference-counting genericized smart-pointer at > > > hand, GC is not necessary at all. In terms of efficiency, I would > > > guess access is at least on par with Eiffel's object ref's. > Try manipulationg complex, dynamic, and circular graph structures. I > think you will have either have to spend a lot of time calling your > destructors and determining which destructors to call. Call them once, > but not twice!
========= Nodes contain ObjectRef<T>'s. "n" nodes, "n" ObjectRef<T>'s, "m" objects. No confusion, no circularities, no problems; just reference counts. Quote: > > Smart pointer schemes require an > > indirection on accessing objects ...
========= There is that. Quote: > > ... and expensive arithmetics on > > duplicating references.
======== Not complex or expensive at all: ++refCount; It's hardly worth mentioning. If you're interested, I can post the other 200 lines of similarly uninteresting code. Compare that with scanning unstructured memory blocks for possible memory references. I'm not arguing against GC. I'm making the point that GC cannot be used to manage other resources; reference counting can, and also does a fair job of managing memory as well. Mike.
|
Fri, 16 Oct 1998 03:00:00 GMT |
|
|
Mike Youn #48 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
Quote:
> Note that although Eiffel is not yet concurrent explicitly, it is concurrent > behind the scenes and we might expect that implementations would perform GC > at appropriate windows of opportunity such as waiting on user input etc.
========== Nothing in the implementation prevents you from deferring deallocation. It would be quite easy to add the unreferenced object to a free list for later reclamation, perhaps by a lower priority thread. Allocation and deallocation is decoupled from reference counting. This allows any resource to be managed symmetrically, including deferred pools. Its declaration is [ template <class T, class Allocator> class ReferenceCount { ... }; ], where allocator is a user supplied class. Just supply an allocator class that manages a free list concurrently. You've got to love a language that allows this granularity of control at a user code level. (Now, if only I could specify that class Allocator requires XYZ interface. :-) Mike.
|
Fri, 16 Oct 1998 03:00:00 GMT |
|
|
Mike Youn #49 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
Quote:
> > > With the STL and a reference-counting genericized smart-pointer at > > > hand, GC is not necessary at all. In terms of efficiency, I would > > > guess access is at least on par with Eiffel's object ref's. > Try manipulationg complex, dynamic, and circular graph structures. I > think you will have either have to spend a lot of time calling your > destructors and determining which destructors to call. Call them once, > but not twice!
========= Nodes contain ObjectRef<T>'s. "n" nodes, "n" ObjectRef<T>'s, "m" objects. No confusion, no circularities, no problems; just reference counts. Quote: > > Smart pointer schemes require an > > indirection on accessing objects ...
========= There is that. Quote: > > ... and expensive arithmetics on > > duplicating references.
======== Not complex or expensive at all: ++refCount; It's hardly worth mentioning. If you're interested, I can post the other 200 lines of similarly uninteresting code. Compare that with scanning unstructured memory blocks for possible memory references. I'm not arguing against GC. I'm making the point that GC cannot be used to manage other resources; reference counting can, and also does a fair job of managing memory as well. Mike.
|
Fri, 16 Oct 1998 03:00:00 GMT |
|
|
Matt Kenn #50 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
: > : > Note that although Eiffel is not yet concurrent explicitly, it is concurrent : > behind the scenes and we might expect that implementations would perform GC : > at appropriate windows of opportunity such as waiting on user input etc. : ========== : Nothing in the implementation prevents you from deferring deallocation. : It would be quite easy to add the unreferenced object to a free list for : later reclamation, perhaps by a lower priority thread. IMHO what should be provided by the GC is a callable function: "how many active references are there to this object?" Then a thread activated every 'n' milliseconds which searches through its list of 'resource-holding-objects' and waits until that count equals 'one' (the one reference being the list of stuff). Then release resources and deallocate memory.
|
Sat, 17 Oct 1998 03:00:00 GMT |
|
|
Paul Johns #51 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
Quote:
>> Try manipulationg complex, dynamic, and circular graph structures. I >> think you will have either have to spend a lot of time calling your >> destructors and determining which destructors to call. Call them once, >> but not twice! >Nodes contain ObjectRef<T>'s. "n" nodes, "n" ObjectRef<T>'s, "m" >objects. No confusion, no circularities, no problems; just reference >counts.
I don't understand this. What little I do understand suggsts that you don't understand the problem. What happens when object A contains an ObjectRef to B, B contains an ObjectRef to C, and C contains an ObjectRef to A? Quote: >> > ... and expensive arithmetics on >> > duplicating references. >Not complex or expensive at all: > ++refCount;
Maybe I'm missing something here, but I would have thought that pointer assignment would look something like this: if (value != NULL) { value->refcount--; if (value ->refcount == 0) { free (value); } } value = new_value; value->refcount++; This is a rather non-trivial amount of code to embed in every pointer assignment. Also note that it de-references and writes to both the old and new objects. This means that they get paged in, and later have to be written out to paging store before something else is paged in. Similar considerations apply to cache locality. Those increment and decrement instructions are actually very expensive. Quote: >It's hardly worth mentioning. If you're interested, I can post the other >200 lines of similarly uninteresting code. >Compare that with scanning unstructured memory blocks for possible >memory references.
So don't write your code in languages like C or C++. Write them in Eiffel. Paul. -- Paul Johnson | GEC-Marconi Ltd is not responsible for my opinions. | +44 1245 242244 +-----------+-----------------------------------------+
|
Sat, 17 Oct 1998 03:00:00 GMT |
|
|
Joachim Durchho #52 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
Quote: > IMHO what should be provided by the GC is a callable function: > "how many active references are there to this object?"
Reference counting is well-known to be inefficient as a method for GC. This is because changing a reference requires a write operation on the newly referenced object (and if the reference was to an object before, the old object will have a write too). This is bad enough, but in a paged environment, this also dirties pages. A mark-and-sweep garbage collector doesn't write pages that don't have to be written. If it is well-written, it is much faster than reference counting, and it can even be used in a real-time environment. The downside is that the number of references to an object won't be available as an incidental result. -Joachim -- Im speaking for myself here.
|
Mon, 19 Oct 1998 03:00:00 GMT |
|
|
Igor Chud #53 / 53
|
The myth of C++ efficiency (reaffirmed! :-)
* > One point to note about garbage collection is the uncertainty it * > introduces about when objects get deleted and what happens at that * > time. The more event driven programming I do (both GUI and interrupt * > driven embedded systems) the more I am beginning to appreciate the * > benefits of being able to create an object and execute its constructor * > routine at the start of a callback then invoke its destructor and * > delete it at the end. Possibly the classic example of this is a GUI * > callback which requires an 'hourglass cursor' during execution. In C++ * > I can write (or reuse of course) an hourglass cursor class whose * > constructor saves the old cursor and replaces it with an hourglass, * > and whose destructor reinstates the old cursor. Placing a local * > declaration of an object of this class in the callback automatically * > guarantees the functionality I want. With GC I would need * > (a) a means of associating a finalisation function with the object * > (b) a way to guarantee that the object got deleted at the end of the * > callback. * I agree what you stated above. GC cannot handle everything. What you gave * is not just one particular thing out of the many, as Matt stated * in his follow-up. If we need to program the object beyond the memory, * such as system resources, persistent objects, network objects, hardware * devices, GC is no longer suitable. There are two uses of destruction: 1) To release system resources (close handles, files, and so on) and 2) To free the memory used by objects in absense of garbage collection. We all agree that if the garbage is collected, there is no need to do 2). As for 1), it is an empirical fact that it needs to be done relatively unfrequently. One could adopt a technique to introduce a feature called `destroy' in classes that use system resources, and call this `destroy' function explicitly. Practically, this method is rather easy to use. Another issue is existence of more practical problems with garbage collection. Try to write a program that implements a simple linked list, create a list of 10,000 to 100,000 elements and try to invoke garbage collector. At least some imlpementations of Eiffel runtime system crash inside garbage collector, because they are implemented using recursive functions. It would be very interesting to see which implementations crash and which do not. - Igor.
|
Mon, 23 Nov 1998 03:00:00 GMT |
|
|
|