5 ms·
> Clearly somewhere in your code you have to explicitly handle tab closing and break the references to allow the GC to do its job. Why not free the resources he
by lossolo 7y ago
> Clearly somewhere in your code you have to explicitly handle tab closing and break the references to allow the GC to do its job. Why not free the resources here while you're at it?
You are missing the point. The main point behind GC is removing the complexity of writing the software. Writing your own destructors, thinking about when to free your memory or writing lifetime annotations, needing to design your app in specific way to satisfy the borrow checker etc in languages like Ada/C/C++/Rust all are additional complexity and mental overhead that is removed by GC.
Your point about "just do this X and you don't need to use GC" is a reason people use GC languages, because they don't want to think about or write this "X".
- irq11 7y agoHaving spent years writing code in both GC’ed and non-GC’ed languages, it’s pretty clear that it programmers spend about the same amount of time worrying about memory management with either paradigm. The main differences are that people using GC systems spend their time doing magical incantations to manage the GC wizard, and they’re a lot more smug about the goodness of their system.
- cblades 7y ago>programmers spend about the same amount of time worrying about memory management with either paradigm I have no idea how you've come to that conclusion. For the vast majority of memory allocation in any GC'd language I can think of, you spend zero time thinking about memory management 98% of the time. whereas in a manual language, you must consider it every time you allocate memory. That's not a bad thing, it's often dead simple in the vast majority of contexts, but still. I've also very rarely seen code in professional code that's mean to poke or prod the GC into running.
- dleslie 7y agoFor 95% of the code you write it's not a concern; that last 5% sure can eat up time if your software has any concern about performance.
- cblades 7y agoTotally agree. I don't think that tradeoff is particularly out-balanced by the time it takes to do manual memory management.
- simias 7y ago>For the vast majority of memory allocation in any GC'd language I can think of, you spend zero time thinking about memory management 98% of the time. >whereas in a manual language, you must consider it every time you allocate memory. This is like bizarro world to me. I genuinely can't comprehend that. Here's how memory management looks like to me, using concrete examples in languages featuring RAII like C++ or Rust: - I have a function that needs to compute a hash so I need to allocate a hash context for it. If it's small I'll put it on the stack, otherwise it'll go on the heap. In either case when the function returns the destructor is automatically called. - I have a function that takes the name of a file as parameter and returns its contents in a buffer. Clearly the buffer needs to be allocated on the heap, so I allocate a large enough vector or string read into it and return that. The caller will then either use it and drop it immediately or store it somewhere to be dropped later, either on its own or as part of the structure it belongs to. In either case the destructor will be called automatically and the memory will be freed. That's easily 99.9% of what memory management looks like in the programs that I write. I have absolutely no idea what using a GC would change at any point here. Note that while this is technically "manual" memory management I never have to explicitly free anything and in the vast majority of cases I don't even have to bother implementing the destructor myself (I basically only need to implement them if I need to release external resources like, for instance, raw OpenGL handles, file descriptors and the like. The GC wouldn't help either here). It's genuinely a non-issue as far as I'm concerned. I literally never think "uh, I have no idea when this object won't be used anymore, I wish I had a GC to figure it out". I can't even imagine when such a scenario would crop up.
- cblades 7y ago>he caller will then either use it and drop it immediately or store it somewhere to be dropped later, either on its own or as part of the structure it belongs to. You're glossing over a lot of complexity there. That's the entire point of GC, you don't have to think about when it's dropped. Also, I wasn't arguing for the blanket necessity of GC in all contexts and for all problems.
- simias 7y agoCan you point out a specific example then? I'm genuinely not trying to play dumb. I very honestly not see that complexity that should be obvious to me given that I spend most of my time writing code in non-GC languages. Maybe it's just Stockholm syndrome and I'm so used to working that way that I don't even see the problem anymore but there are now a long string of replies talking abstractly about the overhead of programming in a non-GC environment and I simply don't relate at all. It's a complete non-issue as far as I'm concerned.
- irq11 7y ago”I have no idea how you've come to that conclusion.” 30 years of experience. ”For the vast majority of memory allocation in any GC'd language I can think of, you spend zero time thinking about memory management 98% of the time.” No, you think about 98% of the code 0% of the time. The remaining 2% ends up causing so many problems that your amortized time spent on memory management is the same.
- simias 7y agoMy point is that you need a "destructor" even with a GC. Continuing with my example you need to pop your tab from the data structure containing your tabs and you have to make sure that all references are dropped so that the GC will do its work. When I write Rust code I basically never have to explicitly free anything outside of FFI code dealing with C pointer or the like. The most straightforward way to allocate anything in Rust is to reify a Box which frees its contents when it's dropped. The data is freed when I remove it from containers or when a Box gets dropped. The closest I get to garbage collection is using a reference-counted pointer here and there (and only after careful consideration). I really don't see what complexity the GC removes in this situation, besides letting you write code without having to care about ownership which, as I stated earlier, I consider to be an antipattern. >"just do this X and you don't need to use GC" is a reason people use GC languages, because they don't want to think about or write this "X" A lazy programmer is a good programmer but it's also important to recognize when something can't be pushed under the rug. I don't want to think about or write documentation and unit tests either, yet here we are. If I had to maintain an application and I ask the coder "when exactly are these objects deleted?" and they answer "dunno lol, I let the GC figure it out" I'd be extremely worried.
- kbenson 7y ago> it's also important to recognize when something can't be pushed under the rug. If you haven't heard of it, you might be interested in the Waterbed Theory of Complexity[1]. The idea behind it is that it's not that you can't push down complexity in an area, but often that complexity just pops up in a different area. For example, you can do away with the vast majority of allocating and freeing memory, but the complexity of doing that pops up again when you start having to tune your GC or use very special patterns to avoid/minimize GC freezes. That's not to say there's not a benefit to that sometimes. If you can push the complexity away from the majority of use cases to a few special use cases, that might be a net win. It doesn't always feel like that though if you're the person stuck trying to coax that last few percent of performance optimizations out of a runtime that only gives you so many levers and dials to work with. I think some of the same concerns that make a dynamic/scripting language a poor choice compared toa compiled and static one are the same things that might make a GC language a poor choice compared to a manually memory managed one, and it's just a matter of scale that separates them. Is performance important? A scripting language might be a poor choice. Is performance really important? Then a GC language might be a poor choice. On the other hand, if I'm writing some program to run correctly once or twice ever, and it might actually take more tome to write than it will ever run for (e.g. a script to parse and/or transform data on disk for me to fix a problem), then is anything really gained from manual memory management? Writing that in Perl or Bash is a valid option there, and that's about as far away from memory management as you can get. For portions of my career, I've spent half or more of my time writing programs like that to help with sysadmin tasks. 1: https://en.wikipedia.org/wiki/Waterbed_theory https://en.wikipedia.org/wiki/Waterbed_theory
- JudgeWapner 7y ago> mental overhead that is removed by GC and it is replaced by GC when your program behaves unexpectedly because, whoopsie, that's the one time the GC decided to run. Good luck debugging or even reproducing that.
- farisjarrah 7y agoJust run your program normally and use eBPF/bpftrace with something like a flamegraph to track your system and its GC. This isn't an easy problem by any stretch of the imagination, however, it is a solved problem.
- ernst_klim 7y ago>that's the one time the GC decided to run. Good luck debugging or even reproducing that. GC usually runs on allocations, so it's quite predictable. The amount of time spent on collection is pretty much as indeterminate as the time spent on malloc/free.
- fouric 7y agoWhen will a correctly-implemented GC ever alter your program's functional correctness, aside from timing-related bugs that aren't fixed by manual memory management either?
- naasking 7y ago> The main point behind GC is removing the complexity of writing the software And more importantly, reading it.