15 ms·
While garbage collection is useful, people often forget that memory is only one resource that needs to be managed. File handles, database connections, sockets,
by rwj 14y ago
While garbage collection is useful, people often forget that memory is only one resource that needs to be managed. File handles, database connections, sockets, etc. also need to be "deallocated". RAII may require programmer effort, but it at least is a complete approach. Generally, I don't think a single technique will win.
- rayiner 14y agoI don't like this argument. It ignores the fact that memory objects outnumber file handles, database connections, etc, by orders of magnitude. Moreover, things like file handles, database connections, and sockets can't refer to other file handles, etc, making them terminal nodes in the in-memory data graph. That makes them a lot easier to manage than memory objects which may appear in any place within a data structure. Finally, the need to create temporary memory objects is far greater, especially in functional programming, than the need to create temporary file handles, etc.
- sausagefeet 14y agoI agree, but I do wish there were more language-level solutions to those resources in GC'd languages. Linear types maybe? I don't know, just something that would keep me from leaking.
- andrewflnr 14y agoI'm not sure what your point is. What part of rwj's argument don't you like? Do you dislike RAII? Personally, it's one of the few things I think I would miss from C++ if I went back to low-level programming. Even if file handles, etc are technically easier to handle, do we really lose anything by using a general tool to manage them, at least sometimes? I feel like I'm missing something. Please explain.
- SamReidHughes 14y agoYou're missing the fact that reclaiming memory under garbage collection does not have any side effects, while reclaiming file handles does. That's why GC is appropriate for memory but not for file handles.
- dkarl 14y agoReclaiming memory makes that memory available for subsequent allocation. Reclaiming file descriptors makes those file descriptors available for subsequent use. Closing database connections means the resources dedicated to those connections are made available for reuse as well. All of those things are resources and fit nicely with the name of the idiom: Resource Allocation Is Initialization. Resource management is 100% about side effects. Not that there's anything wrong with using RAII for things that aren't normally thought of as resources (such as locks) but there's certainly nothing strange about using it to manage a finite resource such as memory.
- SamReidHughes 14y agoIf you think reclaiming memory immediately is a visible side effect, you're deliberately missing the point. Under GC the unused memory just gets reclaimed later. The only visible side effect is the performance differences. That's different than when holding on to a file handle or other resource, for which holding on to the resource until the next GC cycle (which might never happen, ever) would not be acceptable. That's why GC is not acceptable for these resources that are not buffers of memory. At the same time, using RAII for memory management has the obvious downsides that rayiner already iterated through. (One thing he didn't mention was the tragic consequences of getting manual memory management wrong.) (It's telling that you're talking about whether it's strange to use RAII for something, as if anybody here was disagreeing about its relative strangeness. Either you've descended into arguing against an imaginary opponent or you just like switching out your adjectives to different adjectives that have different meaning.)
- deleted 14y ago[deleted]
- dkarl 14y agoReclaiming memory is a visible side effect. If you don't do it, your program leaks memory and dies. Very visible. It's just a resource like any other. I'm not being deliberately obtuse; I'm just recognizing that RAII and garbage collection are mutually exclusive. You're telling me that memory is special because it's managed by GC, but that's a little unfair, because assuming GC renders the entire discussion moot! If you assume garbage collection, then you've ruled out RAII, and there's no point in discussing the suitability of RAII for any resource. You simply can't combine RAII with garbage collection (at least pending some linguistic innovation that involved, say, reference-counting objects only for the purpose of destruction and not for the purpose of freeing memory. Which sounds silly to me.) The reason is that RAII ties resource management to object lifetime, and with GC, there is no deterministic destruction of heap objects, and therefore no such thing as reliable RAII. Without deterministic object destruction, you end up relying on the programmer to manually ensure the destruction of the resource-managing objects. The best you can do in the presence of GC is "with" constructs (such as CL's "with-open-file") which do not give you as strong a guarantee as RAII does, because even with well-designed resource management objects they rely on the programmer to know which types manage resources and to never accidentally use them outside an appropriate "with" construct. Also, there are inevitably times when a resource must outlive the scope of any "with" construct. In the end you are much more reliant on programmer discipline than with RAII. So the question is not whether RAII is suitable for some resources but not for memory, because that is a contradiction given current technology, but rather whether you 1) use RAII both for memory and for whatever additional resources you like, or 2) use GC for memory and use more manual and error-prone (in my opinion) methods for handling other resources. rayiner's objection to RAII is twofold, first that it is simple to manage non-memory resources and second that functional programming style results in a very large number of short-lived objects which are more efficiently handled via GC. To the first I say that managing file handles and database connections may be easy for him, but it certainly hasn't been easy for all the programmers I've worked with. When resource leaks stop being a problem, we'll stop looking for solutions. To the second I say that you can't choose between GC and reference counting on the basis of performance without considering a concrete situation. In many situations it's better to have a program that is consistently slower than one that is much faster on average but intermittently unavailable. In other cases you only care about throughput and will therefore prefer GC. Personally, I prefer to choose on the basis of programmer convenience rather than performance. If resource management is important, that tilts the scales in favor of RAII. If your program naturally lends itself to object graphs with cycles, that points strongly towards a garbage collected language. (Though personally I have never found that reference counting versus garbage collection has been the most important difference between two languages anyway, and the only language I'm aware of that really supports RAII is C++, so it's not like you'll ever make a straight-up decision between RAII and garbage collection without a ton of other very strong factors in play.) That's why GC is not acceptable for these resources that are not buffers of memory. Not to be pedantic... okay, I'm being pedantic ;-) but GC can be used for any set of resources that are linked the way objects in memory are. For example, the database guys at my last job wrote an ad-hoc garbage collector when they realized that buggy triggers had left a ton of orphaned rows in our database.