diguage / www.diguage.com

"地瓜哥"博客网
https://www.diguage.com/
Apache License 2.0
1 stars 2 forks source link

Java 性能测试 #45

Open diguage opened 10 months ago

diguage commented 10 months ago
diguage commented 8 months ago

(CAUTION: Please do thorough testing before implementing below recommendations.)

1

8 min 6 sec 602 ms of GC pause time is triggered by 'G1 Evacuation Pause' event. This GC is triggered when copying live objects from one set of regions to another set of regions. When Young generation regions are only copied then Young GC is triggered. When both Young + Tenured regions are copied, Mixed GC is triggered..

Solution:

  1. Evacuation failure might happen because of over tuning. So eliminate all the memory related properties and keep only min and max heap and a realistic pause time goal (i.e. Use only -Xms, -Xmx and a pause time goal -XX:MaxGCPauseMillis). Remove any additional heap sizing such as -Xmn, -XX:NewSize, -XX:MaxNewSize, -XX:SurvivorRatio, etc.

  2. If the problem still persists then increase JVM heap size (i.e. -Xmx).

  3. If you can't increase the heap size and if you notice that the marking cycle is not starting early enough to reclaim the old generation then reduce -XX:InitiatingHeapOccupancyPercent. The default value is 45%. Reducing the value will start the marking cycle earlier. On the other hand, if the marking cycle is starting early and not reclaiming, increase the -XX:InitiatingHeapOccupancyPercent threshold above the default value.

  4. You can also increase the value of the '-XX:ConcGCThreads' argument to increase the number of parallel marking threads. Increasing the concurrent marking threads will make garbage collection run fast.

  5. Increase the value of the '-XX:G1ReservePercent' argument. Default value is 10%. It means the G1 garbage collector will try to keep 10% of memory free always. When you try to increase this value, GC will be triggered earlier, preventing the Evacuation pauses. Note: G1 GC caps this value at 50%.

2

40.0 ms of GC pause time is triggered by 'G1 Humongous Allocation' event. Humongous allocations are allocations that are larger than 50% of the region size in G1. Frequent humongous allocations can cause couple of performance issues:

  1. If the regions contain humongous objects, space between the last humongous object in the region and the end of the region will be unused. If there are multiple such humongous objects, this unused space can cause the heap to become fragmented.
  2. Until Java 1.8u40 reclamation of humongous regions were only done during full GC events. Where as in the newer JVMs, clearing humongous objects are done in cleanup phase.

Solution: You can increase the G1 region size so that allocations would not exceed 50% limit. By default region size is calculated during startup based on the heap size. It can be overriden by specifying '-XX:G1HeapRegionSize' property. Region size must be between 1 and 32 megabytes and has to be a power of two. Note: Increasing region size is sensitive change as it will reduce the number of regions. So before increasing new region size, do thorough testing.

It looks like you are using G1 GC algorithm. If you are running on Java 8 update 20 and above, you may consider passing -XX:+UseStringDeduplication to your application. It will remove duplicate strings in your application and has potential to improve overall application's performance. You can learn more about this property in this article.

This application is using the G1 GC algorithm. If you are looking to tune G1 GC performance even further, here are the important G1 GC algorithm related JVM arguments

-XX:+UseGCLogFileRotation argument is not recommended to be passed. It can have undesirable effects. To learn more about it's effects and alternative solution refer to refer here.

-XX:+UseCompressedOops is not required to be passed, if you are running in Java SE update 23 and later. Compressed oops is supported and enabled by default in Java SE 6u23 and later versions. For more details, refer here.

-XX:ConcGCThreads=1 has been configured. Less number of GC threads can affect Garbage collection performance. Consider removing this argument. Let the JVM decide the right value for the GC Thread count. (Note: JVM decides the GC thread count based on the CPU/Core count present on the container/host).

It looks like you have explicitly configured Young Gen/Old Gen/Survivor size. In G1 GC algorithm it's advised not to explicitly configure Young or Old generation or Survivor sizes. G1 GC will perform better if you let it make the runtime decisions on the generational heap sizes. Note: However you are welcome to configure perm Gen or Metaspace in G1.