`

【Java 8 GC 调优】并行GC

    博客分类:
  • Java
阅读更多

并行GC,也称为 吞吐量GC,是与 串行GC 类似的 分代GC。其主要区别在于,用多个线程加快垃圾收集速度。
可通过命令行选项 -XX:+UseParallelGC 启用 并行GC。默认情况下,使用此选项后,Minor 和 Major GC 都是并行执行,以进一步减少垃圾收集的开销。
 

在具有超过8个硬件线程的机器上,并行GC 会使用固定占比的数量作为GC线程数。
硬件线程数较大时,该占比为 5/8 。硬件线程数小于8时,GC线程数就是硬件线程数。在特定的平台上,该占比会降到 5/16 。可通过命令行选项指定 GC 线程数(稍后介绍)。
在单处理器机器上,因为并行执行(如,同步)的开销,并行GC 的表现不如 串行GC。
但对于中大型堆的应用程序来说,当运行在双处理器机器上时,并行GC 的性能通常会比 串行GC 稍好一些。有2个以上处理器时,并行GC 的表现会更好。
 

GC 线程数量 可通过命令行选项 -XX:ParallelGCThreads=<N> 来控制。
在已通过命令行显式设置堆大小的情况下,堆大小对良好性能的影响对 并行GC 和 串行GC 是一样的。但是启用 并行GC 应该会缩短暂停时间。
 

老年代碎片化

因为 多个GC线程 同时参与到 Minor GC 中,所以可能会在 “从 新生代 提升到 老年代” 的过程中产生一些碎片。每个 GC 线程都会在 Minor GC 中预留一部分老年代的空间用于“提升”操作。而这个划分 “提升缓冲区” 的操作会产生碎片。
减少 GC 线程数量 和 增大老年代容量 可以降低此“碎片化效果”。

 

“代” 划分

如前所述,并行GC 中“代”的划分方式不同。如下图所示:

 

并行GC Ergonomics

在服务器类机器上,JVM 默认选择 并行GC。此外,并行GC 使用了一种自动调整的方法,它允许你指定特定的行为,而不是“代”容量或其它低级的细节调整。你可以指定 GC 暂停时间的最大值、吞吐量、内存占用(堆大小)。

 

3个 目标

GC 暂停时间最大值

可通过命令行选项 -XX:MaxGCPauseMillis=<N> 指定该最大值。
它会被解释为对GC的提示:暂停时间不能超过 <N> 秒。默认情况下没有最大暂停时间目标。如果指定了暂停时间目标,那么GC会调整 堆大小 及 其它相关参数,以尝试让暂停时间小于指定的值。
这些调整可能会降低应用程序的总吞吐量,而且并不总是能满足暂停时间目标。

 

吞吐量

吞吐量目标是根据 GC所花费时间 与 GC之外所花费时间(称为“应用程序时间”)来衡量的。
应用程序时间占比高就是吞吐量高。
该目标是通过命令行选项 -XX:GCTimeRatio=<N> 来指定的。它表示 GC 时间占总时间的 1/(1+<N>)
例,-XX:GCTimeRatio=19 设置的目标为 GC 时间占总时间的 1/20。默认值为 99,即 GC 时间占总时间的 1% 。

 

内存占用(Footprint)

可通过选项 -Xmx<N> 指定 堆的最大内存占用。此外,GC 还有一个隐含的目标:在满足其它目标的情况下,使堆尽可能小。

 

目标优先级

这些目标的优先级顺序如下:

  1. 最长暂停时间
  2. 吞吐量
  3. 最小内存占用

首先需满足最长暂停时间目标。只有满足它后,才去实现吞吐量目标。同样的,只有前两个目标实现后,才会考虑内存占用的目标。

 

调整“代”大小

GC 保留的统计信息(如 平均暂停时间)在每次收集结束时都会被更新。然后检查是否满足上述目标,如有必要,就会调整“代”的大小。也有例外情况,统计信息更新 和 “代”大小调整策略 会忽略 显式GC操作(如,调用 System.gc() )。
 

GC 会用“代”大小的固定百分比来增大或缩小“代”,使得它满足期望的规模。增大与缩小的比例不同。
默认情况下,增大的比例为 20%,缩小的比例为 5% 。
可通过命令行选项 -XX:YoungGenerationSizeIncrement=<Y>-XX:TenuredGenerationSizeIncrement=<Y> 分别调整 新生代 和 老年代 的增长比例。
-XX:AdaptiveSizeDecrementScaleFactor=<D> 可调整缩小的比例。如果增大的比例为 X%,那么缩小的比例为 (X/D)%
 

如果在程序启动时,GC决定增大“代”,那么它会为“增大比例”加一个补充量。此补充量并不是长期有效的,它会随着 GC 次数的增加而衰减。这个补充量的目的是为了提高启动性能。
“缩小比例”没有补充量。
 

如果 最长暂停时间 不达标,则一次只缩小一个“代”的容量。
如果两“代”的暂停时间都未达标,则会先缩小暂停时间更长的“代”。
 

如果 吞吐量 不达标,则两“代”容量都会增大。每“代”按照各自占GC总时间的比例增大。
例如,如果新生代的GC时间占总GC时间的25%,且新生代的完整“增大比例”为20%,则此次新生代容量会被增大5% (25% * 20% = 5%)。

 

默认堆大小

除非通过命令行指定了堆的初始容量和最大容量,否则将根据机器上的内存量计算。
 

Client JVM 中 堆大小的 默认初始值和最大值

如果物理内存不超过 192MB,则默认最大堆容量为物理内存的一半。否则默认堆容量为物理内存的 1/4 。
 

例如,如果计算机物理内存为128MB,则最大堆容量为64MB;如果物理内存大于等于1GB,则最大堆容量为256MB。
 

除非你的程序创建了足够多的对象,否则 JVM 实际上不会使用到最大堆容量。
JVM 在初始化时会分配小得多的内存,称为初始堆大小。该容量至少是 8MB,或者是物理内存的 1/64 。
 

新生代的默认最大容量是总堆的 1/3 。

 

Server JVM 中 堆大小的 默认初始值和最大值

Server JVM 中 堆大小的默认初始值和最大值 与 Client JVM 类似,只是默认值可能会更高。
在 32位 JVM 上,如果物理内存大于等于4GB,那么默认最大堆容量可以高达 1GB。
在 64位 JVM 上,如果物理内存大于等于128GB,那么默认最大堆容量可以高达 32GB。
你始终可以直接指定更高或更低的初始堆容量和最大堆容量。见下一节。

 

指定 堆的 初始容量 与 最大容量

可以通过 -Xms 和 -Xmx 分别指定堆的初始容量与最大容量。
如果你知道程序需要多大的堆才能正常工作,可以为 -Xms 和 -Xmx 设置相同的值。
如果不指定相同的值,则 JVM 会从初始堆大小开始增大堆,直到找到堆容量和性能之间的平衡。
 

其它参数与选项会影响这些默认值。如需验证这些默认值,可以用 -XX:+PrintFlagsFinal,并在输出中查找 MaxHeapSize 。
如,在 Linux 或 Solaris 中,你可以参照以下命令运行 java:

java -XX:+PrintFlagsFinal  -version | grep MaxHeapSize

 

GC 时间过长 与 OutOfMemoryError

如果垃圾收集耗时过长,并行GC 会抛出异常 OutOfMemoryError。
如果超过 98% 的时间用于垃圾收集,而恢复的堆空间不到 2%,那么会抛出 OutOfMemoryError。
 

此特性旨在防止应用程序运行了很长时间,但由于堆太小而几乎没有进展
如有必要,可通过命令行禁用此特性 -XX:-UseGCOverheadLimit

 

测量

并行GC 的详细输出与 串行GC 基本相同。

 

  • 大小: 7.4 KB
分享到:
评论

相关推荐

    resin-jvm 调优

    java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。 在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能。有些垃圾收集专...

    JVM-Java虚拟机

    资源概要:JVM基础知识;类加载子系统;运行时数据区;对象的创建流程与内存分配;...从广义上讲Java,Kotlin、Clojure、JRuby、Groovy等运行于Java虚拟机上的编程语言及其相关的程序都属于Java技术体系中的一员。

    JVM原理与调优实战下载即用

    设置生代带垃圾对象最大年龄,进量不要有大量连续内存空间的java对象,因为会直接到老年代,内存不够就会执行GC 开发大型 Java 应用程序的过程中难免遇到内存泄露、性能瓶颈等问题,比如文件、网络、数据库的连接未...

    【原价2300!!】尚硅谷_互联网大厂高频重点面试题视频详细讲解

    JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。...下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集器的优化实践。

    2019年互联网大厂高频重点面试题(第2季)

    本期内容包括JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频...下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集器的优化实践

    2019互联网大厂高频重点面试题 (第2季)脑图-完结.txt

    本人吐血整理,git部分未记录(尚硅谷周阳老师的视频脑图) 本期内容包括JUC多线程并发、JVM和GC等...下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集等

    2019互联网面试题第2季.mmap

    尚硅谷周阳互联网大厂面试题(第2季) 脑图。包括JUC多线程并发、JVM和GC等目前大厂笔试中...下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集器的优化实践

    Java虚拟机

    这本书的内容是帮你全面了解java虚拟机,本书第1版两年内印刷近10次,98%以上的评论全部为5星级的好评,是整个Java图书领域公认的经典著作和超级畅销书,繁体版在台湾也十分受欢迎。第2版在第1版的基础上做了很大的...

    尚硅谷_互联网大厂高频重点面试题(第2季).xmind

    下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集器的优化实践。 无论是进入职场不久的初级程序员,还是技术长期没有成长、正在吃老本走下坡路但还想涨...

    java面试常见基础(深层次,高级研发)

    7.1. 目前java中可作为GC Root的对象有 29 8. Redis怎么判断对象可以清理了? 29 9. Redis怎么提高命中率? 29 10. Finalize中调用垃圾回收方法,再调用方法会回收么? 29 11. Int进行自增操作,如何保证线程安全? ...

    第7章-JUC多线程v1.1.pdf

    JAVA线程基本学习, JAVA多线程的特性= 线程池: 本质上是一个对象池, 用来管理线程资源. 在任务执行前, 需要从线程池中拿出线程来执行. 在任务执行完成之后, 需要把线程放回线程池. 线程池好处: 降低资源的消耗...

Global site tag (gtag.js) - Google Analytics