EDIT: I found a post on DDJ discussing some of the limitations of garbage collection that I thought was relevant.
I keep hearing about C++ programming language luminaries doing work on the D programming language. The D programming language pretty much positions itself explicitly as a successor to C++, both with the name, and with various advanced features that otherwise only C++ really offers, such as const, C++ style templates with things like template template parameters, and meta programming facilities. Indeed, it also already offers a number of things that the C++0x committee is only promising for the next version of C++, such as closures.
In addition to that, it ejects the syntactic burden of maintaining compatibility with the C language, and many of the design errors introduced in C++.
Every time I hear about D, I get excited. Yay! <— do you see me being excited?
But then I come back down to earth and and remember D has garbage collection and has no destructors. Now, most people love garbage collection and so do I, when I can use it. Indeed, I wouldn’t say write a web front end in a language where I had to manage memory explicitly. So many people agree that garbage collection is nice, that C and C++ are the only widely used languages that *don’t* have garbage collection by default.
So why am I disappointed? Because the ability to plug in your own memory management scheme, may it be normal heap based, reference counting, memory pool based, or even garbage collection, is the reason *why* people use C++. Garbage collection is a good enough general purpose tool, but it is not a panacea, and people use C++ in places like video games, embedded systems, and interactive applications that need to keep their memory profile under control and can’t afford the inevitable embarrassing paused caused by heap compaction.
Yet, many people love garbage collection so much because of the ease of use it brings, they will engage in intellectual dishonesty to promote it. The page I linked on D garbage collection contains some examples of myths about garbage collection and manual memory management that I can’t see how someone could honestly convince themselves of.
Garbage collected programs are faster (followed by a list of justifications)
This is a weasel phrase. There are multiple measures of program efficiency in computer science, and garbage collection is both in theory and practice worse at two of them. Specifically, garbage collection can *potentially* give better amortized performance, although I don’t believe this has ever been demonstrated in practice. However, garbage collection necessarily gives worse worst case performance, and necessarily has a worse memory profile.
Garbage collectors, even modern ones, periodically compact the heap in order to retrieve memory. This is an operation that touches every piece of memory in the entire entire heap, and it requires all threads be stopped for its duration. Modern systems can have heaps that are many gigabytes in size, so this operation, which occurs non deterministically during your programs run time, can take minutes to execute.
In addition, since not all memory is cleaned up until a compaction happens, the memory profile will be much larger. The way modern generational garbage collectors work, this is primarily a concern with large objects. So if you are writing, say a garbage collected version of Photoshop, you must be very careful how you manage all of your image buffers. Effectively, you must still do manual memory management in order to fight the garbage collectors memory compaction, except in GC only languages, you don’t have the tools to do it properly.
GC also causes problems taking advantage of multi-core systems. If you have a number of threads running, and they each make memory allocations, the rate at which memory allocations made per second will increase with the number of threads, which in turn will increase the number of compactions necessary, each of which requires that requires all threads be stopped through its duration. So garbage collection can, in some scenarios, even impact amortized performance, which I mentioned before was considered the only model by which garbage collection sees a performance *benefit*, by choking all threads on the shared resource of the heap.
In C++ the heap is also a shared resource, but allocations and frees are quick operations that are less likely to spend time in contention. A lot of work has gone into developing versions of malloc that do not lock for long. Furthermore, in those systems where heap contention is a problem, C and C++ provides enough flexibility that the heap can be partitioned into thread specific segments that do not contend.
The authors the D garbage collection FAQ are at least aware of *some* of these problems. However, I can’t take their responses seriously.
Garbage collectors can keep around some memory that an explicit deallocator would not. In practice, this is not much of an issue since explicit deallocators usually have memory leaks causing them to eventually use far more memory
This was true for some C programs in prehistory; however, modern C++ and even C don’t suffer significant memory leaks, and typically have tight memory profiles. I should qualify that, as I’m sure there are still *some* poorly written C programs out there that have memory leaks, but it isn’t the pressing problem it once was. In C++, memory isn’t really managed manually, but via collection and smart pointers that automatically deallocate themselves. I can’t even remember the last time I had a memory leak in C++. Also, for both C and C++ tools are available for tracking down memory leaks if they should occur.
The biggest reason why this is ridiculous is that anyone who has ever used a computer can tell you that the garbage collected programs they use, primarily java’s, consume enormous amounts of memory in comparison to the native C++ applications, even if the java applications are simple whereas the C++ applications are much more complex. This is somewhat subjective, but I think that at the end of the day it is the most compelling argument because all of us spend a lot of time using C++ and java programs, and are aware of their real world interactive performance.
explicit deallocators do not normally return deallocated memory to the operating system anyway, instead just returning it to its own internal pool.
I had a discussion about this on comp.lang.c++.moderated. It turns out *some* mallocs actually do return memory to the operating system by using mmap instead of brk and sbrk. However, it is probably *usually* true that malloc does not unmap pages that have gone out of use, but still irrelevent. It doesn’t really matter how much memory is sitting in the VM, as this only takes up hard drive space if it is never paged in. What matters is how much memory you are going to actually touch. In C++, released memory never gets touched again until it gets reallocated. In a garbage collected system, memory that has not been garbage collected yet, but is no longer in use, will sit there, and maybe be paged out, but it *will* be referenced again in the future during the next compaction. Thus, if you have a bunch of old buffers sitting around that you were using for images or something, they may be paged out to disk, and then paged in on the next compaction. Page faults like this are pricey, to say the least.
Anyway, I think I’m done blowing off steam about garbage collection evangelism. I’d like to emphasize the fact that I still love it, and I advise you use garbage collection wherever you can, but that isn’t everywhere, and it isn’t the the places that C++ has been traditionally used. Thus, I see a “C++ replacement” that doesn’t offer plugable memory mangement like C++ does, as an endeavor going nowhere.
Some of the points I’ve made deserve to be backed up by real world measurements, and I regret they aren’t. I’m actually working on a unit test inspired performance testing system, for fun, right now, so I’ll try to remember to do some related benchmarking when it gets finished.