4 ms·
The 90% reduction doesn't necessarily have to be related only to GC. In my experience Java is a memory hog even compared to other garbage collected languages (
by mrighele 1y ago
The 90% reduction doesn't necessarily have to be related only to GC.
In my experience Java is a memory hog even compared to other garbage collected languages (that's my main gripe about the language).
I think a good part of the reason is that if you exclude primitive types, almost everything in Java is an heap-allocated object and Java objects are fairly "fat": every single instance has an header of between 96 and 128 bit on 64-bit architectures [1]. That's... a lot. Just by making the headers smaller (the topic of the above link) you can get 20% decrease in heap usage and improvements in cpu and GC time [2].
My hope is that once value classes arrive [3][4], and libraries start to use them, we will see a substantial decrease in heap usage in an average java app.
[1] https://openjdk.org/jeps/450 https://openjdk.org/jeps/450
[2] https://openjdk.org/jeps/519 https://openjdk.org/jeps/519
[3] https://openjdk.org/jeps/401 https://openjdk.org/jeps/401
[4] https://www.youtube.com/watch?v=Dhn-JgZaBWo https://www.youtube.com/watch?v=Dhn-JgZaBWo
- formerly_proven 1y agoIf Java's 128-bit object headers are already fairly fat, then what adjective applies to CPython's? [] is about a whole cache line. Trivial Python objects are barely smaller.
- cogman10 1y agoThe java GC approach is somewhat unique compared to other languages. There are multiple GCs and pretty much all of them are moving collectors. That means the JVM fairly rarely ends up freeing memory that it's claimed. A big spike will mean that it holds onto the spike's amount of memory. Many other GCed languages, such as swift, CPython, Go, do not use a moving collector. Instead, they allocate and pin memory and free it when not in use. The benefit to the JVM approach is heap allocations are wicked fast on pretty much all its collectors. Generally, to allocate it's a check to see if space is available and a pointer bump. For the other languages, you are bound to end up using a skiplist and/or arena allocator provided by your malloc implementation. Roughly O(log(n)) vs O(1) in performance terms. Don't get me wrong, the object header does eat a fair chunk of memory. Roughly double what another language will take. However, a lot of people confuse the memory which the JVM has claimed from the OS (and is thus reported by the OS) with the memory the JVM is actively using. 2 different things. It just so happens that for moving collectors like the JVM typically uses more reserved memory means fewer garbage collections and time spend garbage collecting.
- sweetjuly 1y ago> Many other GCed languages, such as swift Swift is not garbage collected, it uses reference counting. So, memory there is freed immediately when it is no longer in scope.
- mrighele 1y agoA moving garbage collector is not that rare, other languages have it. I think C# has one for example, OCaml and SBCL too. I know about the trade-offs that a moving GC does, but the rule is about double memory usage, not ten times more like a 90% reduction would seem to imply.