9 ms·
What should I know about garbage collection as a Java developer?
- dehrmann 4y ago> The pause times with these modern GCs are very small, often units of milliseconds or even lower. This is shorter that a lot of async event loop "pauses."
- turtledragonfly 4y agoOne thing that that I hadn't fully understood until recently is that garbage collectors can actually allow you to write more efficient code. Previously, I had the general understanding that you were trading convenience (not thinking about memory management or dealing with the related bugs) in exchange for performance (GC slows your program down). That's still true broadly, but there's an interesting class of algorithms where GC can give you a perf. improvement: immutable data structures, typically used in high-concurrency situations. Consider a concurrent hash map: when you add a new key, the old revision of the map is left unchanged (so other threads can keep reading from it), and your additions create a new revision. Each revision of the map is immutable, and your "changes" to it are really creating new, immutable copies (with tricks, to stay efficient). These data structures are great for concurrent performance, but there's a problem: how do you know when to clean up the memory? That is: how do you know when all users are done with the old revisions, and they should be freed? Using something like a reference count adds contention to this high-concurrency data structure, slowing it down. Threads have to fight over updating that counter, so you have now introduced shared mutable state which was the whole thing you were trying to avoid. But if there's a GC, you don't have to think about it. And the GC can choose a "good time" to do it's bookkeeping in bulk, rather than making all of your concurrent accesses pay a price. So, if done properly, it's an overall performance win. Interestingly, a performant solution without using GC is "hazard pointers," which are essentially like adding a teeny tiny garbage collector, devoted just to that datastructure (concurrent map, or whatever).
- Alifatisk 4y agoI don’t exactly know how but I’ve always connected GC-languages with slow performance, but today, I realized how wrong I was.
- mike_hearn 4y agoPerformance and GC is a tricky topic, partly because there's not so many GCd languages explicitly designed for performance above usability (maybe D would count? maybe Go?). GC is normally chosen for usability reasons, and then the language has other usability features that reduce performance and it gets difficult to disentangle them. Immutability is a common problem. GC makes allocating lots of objects easy, so people make immutable types (e.g. Java's String type) and that forces you to allocate lots of objects, which causes lots of cache misses as the young gen pointer constantly moves forwards, and that slows everything down whereas a C++ dev might shorten a string by just inserting a NULL byte into the middle of it. Functional programming patterns are a common culprit because of their emphasis on immutability. You bleed performance in ways that don't show up on profiles because they're smeared out all over the program. Another complication is that people talk about the performance of languages, when often it's about the performance of an implementation. The most stunning example of this is TruffleRuby in which the GraalVM EE Ruby runtime often runs 50x faster or more than standard Ruby. Language design matters a lot, but how smart your runtime is matters a lot too. A final problem is that many people associate GC with scripting languages like Python, JavaScript, Ruby, PHP etc and they often have poor or non-existent support for multi-threading. So then it's hard to get good performance on modern hardware of course and that gets generalized to all GC languages.
- turtledragonfly 4y agoWell, there's still truth to it in other cases, I think. One terrible thing GCs can do is make your performance unpredictable. In some performance-sensitive situations (eg: video games), your worst-case perf is more important than your average case. Adding a GC can mess with that worst-case behavior, and in unpredictable ways. That being said, modern GCs are much better (less "stop the world" stuff), and more configurable. But it's still a real concern.
- tester756 4y agoIt's interesting to see that GC is "marketed" to Java developers as some important topic that they all should put effort into meanwhile in .NET world GC is basically outsourced to https://devblogs.microsoft.com/dotnet/author/maoni/ https://devblogs.microsoft.com/dotnet/author/maoni/ and team and their famous gc.cpp https://raw.githubusercontent.com/dotnet/runtime/main/src/coreclr/gc/gc.cpp https://raw.githubusercontent.com/dotnet/runtime/main/src/co... and nobody touches anything but one knob iirc
- moonchild 4y agoAnd .net gc sucks in comparison to java.
- deleted 4y ago[deleted]
- thfuran 4y agoIsn't a more performant GC one of Azul's longest standing selling points for their jvm? It makes sense to me that they'd want to talk about gc.
- adgjlsfhk1 4y agoA lot of the difference is that .NET has actual value types so is less dependent on GC performance. Java came from a brief period when a lot of people thought GCs were magic and so they made their GC problems 10x worse than any other remotely fast language.
- pjmlp 4y agoActually many didn't, except for Smalltalk and SELF, all other languages around that time with automatic memory management did have support for value types. It was a huge mistake to ignore them.
- vips7L 4y agoNowadays with modern Java collectors you really don’t touch any knobs outside of -Xmx (max heap) or if you have special constraints, choosing a different gc implementation like -XX:+UseZGC
- coding123 4y agoStatic variables. Know that you should be extremely cautious with these, especially if you're using them to store big maps or dictionaries or things like that. Beyond statics, honestly, never ran into anything else that's not cured by changing your command line a bit.
- dehrmann 4y agoClasses can also be GCed in Java, but obviously only if they're no longer referenced.
- bberrry 4y agoPresumably if you're creating a large map in memory it's being used, no? Or did you have something static that was really only used during startup?
- Brystephor 4y agoWhy are these relevant or special for the GC in a "gotcha" manner?
- karmakaze 4y agoBecause a static reference causes objects referenced by it to never be GC'd. As a simple hack, someone might add a singleton implemented as a static field of a class. That reference could be/have a structure/collection that accumulates and never gets freed. You can find these things using the Java Memory Analyzer and the OQL it supports. Sometimes easy sometimes tricky.
- rcgorton 4y ago[dead]
- datavirtue 4y agoBe nice to your garbage collector. Don't leave references to objects that are not needed. Once they are done, and the scope is going to remain, null them.
- ramranch 4y agoWhy not just write C, then? Sounds like you're just setting up for NPEs
- nlitened 4y agoOr use a language that does it automatically, like Clojure
- thewisenerd 4y agois this a reference to the 2019 talk, or are you being serious (in which case, could you please share a couple references)? context: https://www.youtube.com/watch?v=ocUx-QUJMfo&t=630s https://www.youtube.com/watch?v=ocUx-QUJMfo&t=630s