
Epsilon: The JDK’s Do-Nothing Garbage Collector - based2
https://blogs.oracle.com/javamagazine/epsilon-the-jdks-do-nothing-garbage-collector
======
walkingolof
JVM GC development has seen an upswing in the last few years, one of the most
interesting new GCs are ZGC that show impressive numbers, delivers less than
10 ms pause times for any heap size, often than 1 ms for many applications,
while having impressive throughput numbers. Another interesting adoption to
the containerized world we live in is that GCs recently started to frequently
return memory to the OS when not being used.

If you want to read more about these new GCs, this is a great post:
[https://blog.plan99.net/modern-garbage-collection-
part-2-1c8...](https://blog.plan99.net/modern-garbage-collection-
part-2-1c88847abcfd)

~~~
kjeetgill
Don't forget Shenandoah headed by G1's lead Christine Flood! I don't know
enough to compare it to ZGC but it's an exciting time in Java's GC lineup.

~~~
lightgreen
They promised low latency in G1, then they promised low latency in Shenandoah,
now they promised it in ZGC.

Okay.

What JVM really really needs for performance is value types: a lot of GC
problems will simply not exist with value types.

Project Valhalla started five (!) years ago, and they are still working on it.

JVM could also use multiple heaps per process (so multiple GCs could run
independently not affecting other heap execution and GC). There were talks
about it years ago, but nobody is working on it AFAIU.

~~~
peterashford
G1 _has_ low latency. And as someone who programs c# for a living: I DO NOT
WANT value types.

~~~
tom_mellior
Interesting, could you expand a bit? From what I have seem the proposal for
Java seems useful.

~~~
peterashford
In the c# I dislike the extra mental load of having to work out which rules
apply to the lexical thing I see being manipulated in the code. If I see
references being assigned in Java I can tell that that's the case just by
looking at the code. In c# I have to see the definition of the objects to tell
what semantics are being expressed by the syntax. Likewise, with properties in
c# a straightforward field assignment can be pretty much anything which means
again, innocent looking code can be misleading and the only way to know is to
read the definitions. Java is simpler to read and I value that.

------
pjc50
See also Raymond Chen:
[https://devblogs.microsoft.com/oldnewthing/20180228-00/?p=98...](https://devblogs.microsoft.com/oldnewthing/20180228-00/?p=98125)
\- who quotes the story of a piece of embedded software which accepted leaking
since it would be used in the runtime of a missile.

~~~
MaxBarraclough
Similarly, the cooling solution for some missiles' control-systems' is simply
'thermal inertia', i.e. they just race against overheating, as program-
termination can be relied upon to occur first.

------
emmericp
Related: I ran some benchmarks for all GCs in OpenJDK 12 some time ago:
[https://github.com/ixy-languages/ixy-
languages/blob/master/J...](https://github.com/ixy-languages/ixy-
languages/blob/master/Java-garbage-collectors.md)

Epsilon tied on speed but lost to Shenandoah on latency because never freeing
memory isn't ideal either, even if you never run out of memory.

~~~
CoolGuySteve
Ya if you allocate/deallocate onto a stack, the most recently freed memory is
more likely to be hot in the cache for the next allocation, reducing overall
latency.

It’s something I do all the time in C++.

------
etaioinshrdlu
Speaking of garbage collectors, I had a thought the other day, wondering if
performance could have a huge linear speed up if the graph of object pointers
was stored compactly in memory, separated from the rest of an application's
memory.

The object graph could be stored in a succinct compressed format to reduce
it's size as much as possible, compared to actual 64 bit pointers.

Then the GC algorithm could crawl the graph much much faster by virtue of
needing to access far fewer memory pages, and increased likelihood that those
pages will be in a fast cpu cache most of the time.

~~~
smaddox
Luajit does something vaguely like this: [http://wiki.luajit.org/New-Garbage-
Collector#arenas_block-ma...](http://wiki.luajit.org/New-Garbage-
Collector#arenas_block-mark-bitmaps)

It doesn't need to access the actual data when sweeping.

~~~
ufo
The latest version of LuaJIT is still using the old GC. As far as I know the
new GC design is in limbo, with no plan to implement it in the near future.

------
BLanen
I think this article about Instagram turning off Python's garbage collecting
is somewhat relevant and interesting:

[https://instagram-engineering.com/dismissing-python-
garbage-...](https://instagram-engineering.com/dismissing-python-garbage-
collection-at-instagram-4dca40b29172)

~~~
z92
Read it. It's still garbage collecting, but doing it through reference
counting. There was an extra GC for circular reference collecting. That one
was disabled as well as object freeing up before termination.

------
capableweb
Now I'm no Java expert, far from it, so would appreciate any answers to this.
I'm interacting with bunch of CLIs that are either in Java or using the JVM
otherwise (Clojure mostly), how much of the startup time for this things can
be attributed to the GC? It's mentioned in the article that short-running
programs (almost all CLIs I use) could use Epsilon since the heap is cleared
on exit anyways. But wondering how much of the typical program actually spends
on, what I guess is initializing the GC?

~~~
kasperni
I think the overhead of GC is negligible for many small programs. Claes
Redestad @ Oracle gives a good overview here.
[https://cl4es.github.io/2019/11/20/OpenJDK-Startup-
Update.ht...](https://cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.html)

I would look into GraalVM native images if you want fast startup.

~~~
MaxBarraclough
There's some precedent for chopping out the GC for short-lived applications.
DMD, the (self-hosting) D compiler, does this, effectively using a push-only
stack for the heap, never doing anything akin to freeing memory. [0]

In modern GCs, allocation is already as fast as can be (pointer-bump
allocation), so I imagine the only win in chopping out the GC is that you
don't need to initialize the GC (it's otherwise roughly equivalent to simply
terminating before the GC needs to be invoked).

Perhaps the DMD example isn't quite the same, though, as it's possible its GC
has slower allocation than pointer-bump.

[0] [https://www.drdobbs.com/cpp/increasing-compiler-speed-by-
ove...](https://www.drdobbs.com/cpp/increasing-compiler-speed-by-
over-75/240158941)

------
mike_hock
To address the short-running program issue, can't the regular GCs just not
clean up on program exit?

~~~
jelllyounf
Perhaps there may be objects that depend on the finalizer callback for
correctnesss. I have seen people use finalizer to do things like close file
handles, and presumably not calling close may not guarantee data is persisted.

~~~
jlokier
At least on unix systems, process termination implicitly calls close() on
every file descriptor anyway. There should be no need to call it explicitly.

(You won't get the chance to log any write errors reported by close() or react
to the errors, though.)

------
microcolonel
It'd be nice to have a per-thread mode for this.

------
dmitryminkovsky
Probably good for running Java on your cruise missile.

~~~
AndrewBissell
Peter Lawrey said he had HFT clients who wrote Java and managed to get their
object allocation so low that they never had a GC pause, and just waited until
market close to restart the JVM.

~~~
aidenn0
A number of games written in managed runtimes will pre-allocate a large number
of objects at the start of each level/zone, and hope they don't run out before
the next level (where a GC can run).

