In several journals, articles, and blogs all throughout the internet there is one common theme: “Serial GC is not meant for any serious application. It should be used only for prototype applications. It’s only meant for desktop applications or applications that have a few hundred MBs of heap size. It shouldn’t be used in production.” To question this status quo theme, we conducted the below study on a major travel webservice application in North America (Apologies, I can’t disclose their name).
We believed this sort of study would yield more meaningful results when conducted in real production traffic. So we configured 2 servers, one with G1 GC setting and the other with Serial GC Setting in a production environment. We picked G1 GC as it’s the latest GC collector and default GC collector since Java 9. All other servers in production environments were running with the old GC setting (which is of no interest to this article). A load balancer was equally distributing the traffic across all the servers. We let the servers run for a 24 hour period on a working day so that servers can experience both high and low traffic volume. This application runs on RedHat Linux 5.x, Java 7, Tomcat 7, and services SOAP requests. It uses popular frameworks such as Axis2, Spring, and Apache Commons.
Below are the two GC Settings that were instituted:
G1 GC: -Xms6144m -Xmx6144m -XX:MaxPermSize=512m -XX:PermSize=300m -XX:+UseG1GC -XX:MaxGCPauseMillis=500 Serial GC: -Xms6144m -Xmx6144m -XX:MaxPermSize=512m -XX:PermSize=300m -XX:NewSize=4608m -XX:MaxNewSize=4608m -XX:-UseSerialGC
The following tools were used for this study:
CPU and memory utilization metrics were captured from the APM tool New Relic
Throughput and Latency metrics were captured from universal garbage collection analysis tool http://gceasy.io/.
Tuning Serial GC
As it’s recommended that G1 GC will dynamically adjust the generational space, we didn’t specify any young or old generational size.
On the other hand in Serial GC setting, we configured the Young Generation size to be 4 GB, which is 2/3rd of the overall heap. We intentionally declared such high young generational size, because we know for this application, significant of the objects are short-lived. As it’s a Webservice application, when a SOAP request enters the application, a lot of objects are created. Once the request is serviced and response is sent back, all of those objects die down. There are very limited long-lived objects. Thus we intentionally tuned the young generation size to be larger than the old generation size.
Key Performance Indicators
The below table summarizes the KPI metrics of this study. For more details and graphs, please click on the hyperlinks provided in the 'Detailed Report' column (which I highly encourage to do):
|Avg CPU Utilization||Throughput||Latency||Detailed Report|
3 secs 110 ms
|G1 GC Report|
2 secs 640 ms
|Serial GC Report|
There are several interesting observations in this study:
1. CPU Spike in G1 G
You can notice that CPU consumption was slightly higher in G1 GC settings (25.1%) than Serial GC settings (23.3%). Leaving that fact aside, we ran into an issue during server startup time. There were significant CPU spikes in G1 GC settings during server startup time. It caused the load balancer to evict the G1 GC enabled server from its pool. Thus only after few minutes of server startup time when CPU utilization settled down, we could add back the G1 GC server to the load balancer.
2. Comparable Throughput
Throughput in G1 GC is 97.62%, whereas serial GC is 98.27%. Throughput is marginally better in Serial GC.
3. Better Latency in Serial GC
To everyone’s surprise, the max GC pause time (i.e. latency) of Serial GC is better than G1 GC J. Serial GC’s maximum pause time is 2 secs 640 ms, whereas G1 GC’s maximum pause time is 3 sec 110 ms. This is despite the fact that G1 GC’s max pause time is configured to 500 ms.
This study makes us question the validity of the status quo statement: “Serial GC is not for serious applications”. This study also reveals that tuning Serial GC with ‘human intelligence’ would be able to provide better or comparable results with ‘machine intelligence’ tuned G1 Garbage collector algorithm. Please share your comments, criticism, and feedback on this study. Looking forward for a healthy conversation.
Note: This article is in no way meant to offend the G1 GC algorithm and its fans. In fact I am a big fan of G1 GC because of its auto-tuning capabilities and capability to set a max pause time option. These features are a boon to the development community. Of course it’s needless to say that a properly tuned G1 GC setting might be able to deliver better results than default or out of the box G1 GC settings that were used in this study.