ParNew gc long pause
https://bugs.openjdk.java.net/browse/JDK-8079274
Here's what happens:
To be able to parallelize the GC work ParNew divides areas that has to be scanned into smaller chunks. Each worker thread is then given a chunk to look at.
Area to be scanned divided into chunks:
|----------|----------|----------|----------|----------|----------|
When processing a chunk, the worker thread must first find out if there is an object spanning the border of the chunk. To do that the thread will scan from the start of the chunk towards lower addresses to find the start of an object.
Object spanning the border between chunks:
|----------|----------|-------Ooo|oo--------|----------|----------|
In this example the thread who is given the chunk that starts in the middle of the object will have to scan to the left of the chunk until it finds the capital O where the object starts. If the object is large, this will take time.
In the case described in this issue the object is really large and spans several chunks. This means that all worker threads have to scan a long way to find the start of the object several times. This is what consumes the time and causes the long GC pauses.
The default size of these chunks is fairly small. To increase it use -XX:ParGCCardsPerStrideChunk. The default is 256, setting it to larger numbers will get rid of the long pause in this example. I went as high as 1m but you need to tune this with your application to see what works the best for you. Setting high values may affect other aspects of your GC experience.
It seems that you have found the exact border where the object spans exactly as many chunks as possible. A larger object probably triggers some higher level code that are able to skip scanning of this part of the memory.
So, why doesn't this happen with DefNew in 1.6 and 1.7? Well, the answer is that DefNew does not divide the area into chunks since it does not parallelize this work. It simply start from the bottom (left) of the area and scans forward. When it finds an object it can immediately see the size of this object and jump past it to continue scanning. This can be emulated with ParNew as well by setting -XX:ParallelGCThreads=1 and disable the parallelism. Try it out and you will see that the long GC pauses goes away. This will however also affect CMS so I'm not sure if it is a satisfactory solution in your case.
This is not something that we can easily change in the ParNew collector. It is this way by design. There may be ways to mark chunks so that they only need to be scanned once and by doing so avoid the repeated scanning that consumes the time here. I'm not sure if that is something we want to do considering that we are actively working on replacing these old collectors with G1. In any case this is not a bug, but would rather be an enhancement request. I'll leave it open for now and bring this case up with the rest of the team to see if it something that we should consider fixing. I doubt such a change would be allowed into 8u60 though since it would be a high risk change with lots of potential new bugs. If it is fixed it will most likely be for JDK 9 or later.
浙公网安备 33010602011771号