如何调整G1GC以缩小内存占用量?

时间:2016-04-06 12:39:51

标签: java jvm g1gc

我一直在我的一个项目上使用Java 8(Oracle JVM)试验G1GC。我的GC标志是有效的:

-Xms64m
-Xmx1024m
-XX:+UseG1GC
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-Xloggc:/tmp/gc.log
-XX:+PrintAdaptiveSizePolicy

我观察到堆的增长比我拥有的实时数据量大得多。 GC日志显示了我认为的根本原因:

[G1Ergonomics (Heap Sizing) attempt heap expansion, reason: recent GC overhead higher than threshold after GC, recent GC overhead: 10.17 %, threshold: 10.00 %, uncommitted: 811597824 bytes, calculated expansion amount: 162319564 bytes (20.00 %)]

实际上,我的应用程序产生了大量垃圾,因此在GC中花费的时间比例高于10%,因此G1的人体工程学设计增加了堆大小。

使用并行收集器,可以使用-XX:GCTimeRatio(吞吐量目标)调整此阈值,但是从docs中可以看到,G1没有等效标志。

  

对于并行收集器,Java SE提供了两个基于实现应用程序的指定行为的垃圾收集调整参数:最大暂停时间目标和应用程序吞吐量目标;请参阅并行收集器一节。 (这两个选项在其他收集器中不可用。)请注意,这些行为并不总能得到满足。

我的问题是,除了降低最大堆大小外,我如何调整G1GC以减小内存占用量?

在日志中没有证据表明我绊倒了最大暂停时间目标,并且实际上增加了这个并不能解决问题。

这可能是这个问题的一个骗局:Which JVM Flag sets the GC overhead threshold mentioned in the G1Ergonomics log?,但看起来似乎接受了错误答案。 (或者它可能仅适用于较旧版本的JVM。)

2 个答案:

答案 0 :(得分:2)

<强>概述:

  • this Oracle article(1)中,您可以找到G1最重要的标志(包含-XX:MaxGCPauseMillis)。

  • This bug report表示{G1}中也使用GCTimeRatio标志。

  • 另请参阅this related question & answer(2)。

  • 我认为你应该能够通过将-XX:MaxGCPauseMillis设置为更高的值来解决这个问题,或者如果你知道你的应用程序创建了很多(年轻的)垃圾,你可以使用有关大小的设置年轻一代。编辑:好的,要非常小心,(1)陈述: *年轻代大小*:避免使用-Xmn选项或任何或其他相关选项(如-XX:NewRatio)明确设置年轻代大小。修复年轻一代的规模会覆盖目标暂停时间目标。

(1)

重要默认值:

G1 GC是一个自适应垃圾收集器,其默认设置使其无需修改即可高效工作。以下是重要选项及其默认值的列表。此列表适用于最新的Java HotSpot VM,版本24.您可以通过在JVM命令行上更改设置输入以下选项来调整和调整G1 GC以满足应用程序性能需求。

  • -XX:G1HeapRegionSize = N

设置G1区域的大小。该值为2的幂,范围从1MB到32MB。目标是根据最小Java堆大小来拥有大约2048个区域。

  • -XX:MaxGCPauseMillis = 200

设置所需最长暂停时间的目标值。默认值为200毫秒。指定的值不适合您的堆大小。

  • -XX:G1NewSizePercent = 5

设置要用作年轻代大小的最小值的堆的百分比。默认值是Java堆的5%。这是一个试验性的旗帜。请参阅&#34;如何解锁实验性VM标记&#34;举个例子。此设置将替换-XX:DefaultMinNewGenPercent设置。此设置在Java HotSpot VM,build 23中不可用。

  • -XX:G1MaxNewSizePercent = 60

设置要用作年轻代大小的最大值的堆大小百分比。默认值为Java堆的60%。这是一个试验性的旗帜。请参阅&#34;如何解锁实验性VM标记&#34;举个例子。此设置将替换-XX:DefaultMaxNewGenPercent设置。此设置在Java HotSpot VM,build 23中不可用。

  • -XX:ParallelGCThreads = N

设置STW工作线程的值。将n的值设置为逻辑处理器的数量。 n的值与逻辑处理器的数量相同,最大值为8。

如果逻辑处理器超过八个,则将n的值设置为逻辑处理器的大约5/8。这在大多数情况下都有效,除了较大的SPARC系统,其中n的值可以是逻辑处理器的大约5/16。

  • -XX:ConcGCThreads = N

设置并行标记线程的数量。将n设置为并行垃圾收集线程数(ParallelGCThreads)的大约1/4。

  • -XX:InitiatingHeapOccupancyPercent = 45

设置触发标记周期的Java堆占用率阈值。默认占用率是整个Java堆的45%。

  • -XX:G1MixedGCLiveThresholdPercent = 65

设置要包含在混合垃圾回收周期中的旧区域的占用率阈值。默认入住率为65%。这是一个试验性的旗帜。请参阅&#34;如何解锁实验性VM标记&#34;举个例子。此设置将替换-XX:G1OldCSetRegionLiveThresholdPercent设置。此设置在Java HotSpot VM,build 23中不可用。

  • -XX:G1HeapWastePercent = 10

设置您愿意浪费的堆的百分比。当可回收百分比小于堆废弃百分比时,Java HotSpot VM不会启动混合垃圾回收周期。默认值为10%。此设置在Java HotSpot VM,build 23中不可用。

  • -XX:G1MixedGCCountTarget = 8

在标记周期后设置混合垃圾收集的目标数,以收集最多具有G1MixedGCLIveThresholdPercent实时数据的旧区域。默认值为8个混合垃圾收集。混合收集的目标是在此目标数量范围内。此设置在Java HotSpot VM,build 23中不可用。

  • -XX:G1OldCSetRegionThresholdPercent = 10

设置混合垃圾回收周期中要收集的旧区域数量的上限。默认值是Java堆的10%。此设置在Java HotSpot VM,build 23中不可用。

  • -XX:G1ReservePercent = 10

设置保留空闲的百分比以保持空闲,从而降低空间溢出的风险。默认值为10%。增加或减少百分比时,请确保将总Java堆调整相同的量。此设置在Java HotSpot VM,build 23中不可用。

(2)

我的猜测是recent GC overhead higher than threshold正在推动G1的决定。您可以通过设置-XX:GCTimeRatio=4来放宽它,这将使其相对于GCing的应用时间占用20%的CPU周期而不是10%。

如果那太多你应该

  • 允许它使用更多的CPU内核 - 这样可以更轻松地实现其暂停时间目标,这反过来又意味着它可以延长集合的时间,从而更容易满足吞吐量目标。 是的,这意味着使用更多内核实际上可以使用更少的CPU周期。

  • 放松暂停时间目标,以便不必经常收集

答案 1 :(得分:0)

经过进一步调查后,看来G1的人体工程学确实尊重-XX:GCTimeRatio,尽管文档说的是什么。