Observations about Shenandoah
For everyone who has read our Java Garbage Collection handbook, the concluding portions allude to an upcoming garbage collection algorithm named Shenandoah. Since the time of that writing, some major efforts have come to fruition. This post is aimed at being an introduction to some technical and some not-so-technical aspects of these recent changes.
Observation #1: Community contributions
Ever since Java began to be adopted widely as a programming language, community contributions have kept the ecosystem thriving. With the changes in corporate structure around the Java world, with Oracle’s acquisition of Sun Microsystems, it was feared that there might be a lot less innovation in the Java space.
It came as a big relief to Java enthusiasts from around the world that community-driven contributions to JDK 12, and naturally to OpenJDK showed a healthy trend. Both the Shenandoah and ZGC garbage collection algorithms included in the latest JDK releases have been efforts led by teams at Oracle (for ZGC) and RedHat (Shenandoah). It reinforces the faith that the community has about Java being open.
Observation #2: Garbage Collection isn’t a solved problem!
Far from it in fact. Plenty of efforts are underway to reduce the impositions that garbage collection places on programmers. With the introduction of Shenandoah and ZGC, there are six very popular GC algorithms available for the JVM.
As opposed to popular belief, Shenandoah is suited for applications not just with large heaps. Engineers have reported of benefits they have gained from running it on applications with smaller heaps in the order of hundreds of megabytes.
Both ZGC and Shenandoah originated with similar goals. However, their approach to solve the same problems could not be more different. The ZGC implementation happens using multiple-memory mappings and colored pointers, whereas Brooks pointers are used for implementing Shenandoah.
There is still plenty of ongoing work to make the arithmetic and algorithms better with regards to garbage collection.
Observation #3: Shenandoah is no silver bullet.
In continuation with the previous observation, the dynamic requirements of engineering environments demand garbage collection to be optimized for different needs. There is no automatic way to specify which garbage collection algorithm is best suited for your system. The trade-offs are specific to each system. Algorithms operational currently are optimized for throughput, latency, (low) memory footrints. Shenandoah being no exception.
Usage of Shenandoah introduces predictability into pauses that garbage collection introduces. The use of Shenandoah is not a guarantee against any pauses. Instead, these pauses transform into a parameter that can be accounted for while architecting systems and estimating capacity.
There isn’t a simple way to choose a garbage collection algorithm. You don’t have to be stuck with the default either. Investigate the needs of your applications and make an informed decision about which one will suit your needs best. Benchmarking your applications in staging are a good way to narrow down on a choice. Observing behaviour on production and making a permanent choice is the right way.
Attaching Plumbr agents is a great way to know how your JVMs behave in production. Plumbr gives you the best overview of JVMs in production. Using information from Plumbr to characterize the behavior of your choice of GC algorithms can help ease this decision making process.
Observation #4: Where did they come up with this name? #JustAsking
We haven’t found an answer to this question across the many papers we’ve read and talks we listened to about Shenandoah. If you do happen to know, please tell us!
We will follow up with a few posts about some benchmarking experiments and performance considerations when using Shenandoah. Stay tuned!
Thanks to Nikita for his help composing this post.