6 ms·
Three bad things: threads, garbage collection, and nondeterministic destructrors
- j_baker 16y ago"Then you can create a file, write to it, and close it, all in one line. The closing is implicit, of course; it happens right away as soon as there are no more references to the file. Because, obviously, nothing else would make sense." This behavior isn't even guaranteed in CPython (and never has been as far as I know). There's a problem with deterministic destructors and refcounting: if there's a reference cycle, which destructor gets called first? import weakref import gc class Something(object): def __init__(self, other): self.other = other def __del__(self): print '__del__ called!' s1 = Something(None) s2 = Something(s1) s1.other = s2 del s1 del s2 gc.collect() print gc.garbage Even the cyclic garbage collector won't pick this up. These kinds of issues come up more and more if you rely on python's __del__ methods (aka destructors). The solution? Quit complaining and just use a with block. It isn't that bad.
- btilly 16y agoWith reference counting, those issues are never caught.
- j_baker 16y agoIt's not just about reference counting though. It's a weakness of deterministic destructors. When you have a reference cycle, it's impossible to call destructors deterministically even if you aren't using reference counting.
- jmillikin 16y agoThe author spends a lot of time claiming garbage collection is bad because it can't solve problems it wasn't designed to solve. Garbage collectors are for freeing memory allocations. If you're using them to manage scarce resources (file descriptors and sockets, especially), your design is already broken. Ditto destructors -- you should write your code such that a destructor closing a resource is considered a programming error. assert(FALSE) in a debug build, log it in production, but don't just let such a bug creep silently by. The only exceptions are C++ RAII wrapper classes, which are designed to have magical destructors. C#'s using(), Python's with statement, Haskell's with* functions -- they're all designed to solve the problem that a generic garbage collector doesn't and shouldn't, which is "I need precise control over the lifetime of this resource allocation". Java doesn't have such a mechanism, but then, Java doesn't have much of anything for a supposedly high-level language. C doesn't have such a mechanism, but that's OK, because it also doesn't have exceptions. Additionally, programming with threads is much less complicated than the author is making it out to be. Sure, it's hard if you're manually (un)locking mutexes like a damn caveman -- but every major high-level language available today (except, again, Java) provides better abstractions. Some, like Erlang and Haskell, make concurrent and parallel programming especially easy. Finally, if you can get by with a single-threaded, refcounted, deterministic program -- go ahead. Have fun. The rest of us, here in the real world, have applications more complicated than a high-school midterm to work on. And customers won't pay you if the user interface is sluggish because you were too ignorant to write a proper thread pool.
- cdavid 16y agoAnother point worths mentioning is the recurring, bogus argument about GC, non-determinism and comparison with malloc. If you think malloc is any more deterministic than gc, you are kidding yourself: think about what happens when malloc gives you a block that contains pages which will be pulled from disk when you access them. When you want to program something which has low, guaranteed latency, you locks your pages in memory, and you never calls malloc in that thread.
- InclinedPlane 16y agoJava was an innovative language when it came out. But future proofing byte-code put a very tight lid on innovation (resulting in generics hampered by type erasure, for example) and the language has very much stagnated at the same time many other languages have innovated like crazy.
- ewjordan 16y agoAs long as Oracle doesn't decide to scrap the set of promises that Sun had made for Java 7, that release will resolve many complaints and bring the language forward a bit, at least. It's not going to make Java the most powerful language around by any means, but it will help, and I think we'll start to see much tighter Java code coming out, at least from the people that know what they're doing. For one thing, it will finally add automatic resource management blocks, which by my understanding do exactly what is being complained about here - they let objects deterministically clean up after themselves without relying on finalization. What I'm still skeptical about is whether closures will actually make it in or not...it's much harder to add them on after the fact (while still maintaining backwards compatibility) than it is to design a language around them from the start, and I'm not really convinced that Oracle will care enough to see the efforts through to the end; at the very least, I don't see it as likely that it will happen without a serious schedule slip.
- InclinedPlane 16y agoJava's chief weakness has been it's lack of first class functions. If closures don't make it in to Java 1.7 then it's game over, it'll be sealed as the COBOL of our times.
- antareus 16y agoD seems to be more sensitive to these concerns than other languages, at least as of late. Classes can be marked as "auto", which indicates they are to be destructed deterministically. I think this is a more elegant solution than requiring users to opt-in to proper semantics, though requiring the auto specifier at the use-site would make things more explicit. Also, most languages have some sort of thread-based tasking framework that can make it easier to implement async message-passing based concurrency.
- acqq 16y agoIt's still bad, since it will lead to the effect "just write every class with auto." C++ combined memory allocation and the object destruction in one thing and now we have too many people that think those should be one primitive. They shouldn't. Once you recognize that you have to care about both separately, you start to recognize that even GC is an answer to the wrong question. For really "cool" programs (using the most of the resources etc) you simply have to manage memory yourself. Object should not manage their allocation, they should just "know" who's in charge for their allocation. Some Bloomberg guys recognized that and made some libraries for C++, ans some work was done to get something like that in C++ standard, but I don't know if the result is useful. I also don't know if such ideas would look nicer in D.
- SamReidHughes 16y agoI'm somewhat confused by the D documentation. The documentation refers to "auto objects" in the prose somewhere, but it seems to refer to the feature as "scope classes" and uses the scope keyword to do so. Here is the page I am referring to: http://www.digitalmars.com/d/2.0/class.html http://www.digitalmars.com/d/2.0/class.html . The reference also says the use of the scope keyword is required at the declaration site for references to scope classes.
- pmjordan 16y agoThe problem I can see with specially tagging types like that is that you can't compose them within classes that use GC. The determinism is viral. You could make it an error to rely on destruction for resource release, but what stops the programmer from wrapping the resource in an object of his own making, and freeing the resource in the wrapper's destructor? Walk the stack to check if the code is called from ANY destructor?
- houseabsolute 16y agoMeh. Locking is going to be a requirement if you have mutable shared state. Whether it's threads or events that are driving it, the possible classes of problems look almost identical. Merely having a drawback doesn't make something bad. So garbage collection cannot run destructors deterministically. That is indeed unfortunate but it in no way outweighs the benefits -- for example, that the vast majority of classes which don't hold these kinds of resources can just be discarded and forgotten. It's kind of a stupid thing to say that this alone makes them bad. It would be like if I said, "Feet suck because they can step on nails." Wait, that's not quite right.
- philwise 16y agoPlease, this is ridiculous. Find me a professional programmer who doesn't consider garbage collection and threads to be a useful thing.
- ewjordan 16y agoMy favorite bit: So far, the vast majority of the programs I write have been single-threaded, refcounted (or manually memory managed), and deterministic. I think I'll continue to do it that way, thanks. Well, gee, I'm so glad that's cleared that up for me - here I was, writing multi-threaded/non-deterministic code all over the place, just because I like it so much. Tracking down race conditions is a choice, we can choose not to get involved with any of it, and we'll be just fine! Some guy on the Internet says so, it must be true!
- jbooth 16y agoWell, you can write deterministic code in Java using threads, just use defined constructs that give you guarantees about how things will be executed and orders -- ExecutorService and BlockingQueue are your friends.
- js4all 16y agoReal life shows, ref-counting, when done manually, is more error-prone then GC. Programmers make errors. As single missing release keeps your object locked in memory. One missing add-ref crashes your program. Microsoft soon learned this lesson after the introduction of COM and quickly added smart pointers. Still not a good solution. For their followup technology (.Net) they used GC. Lession learned.