GC调优到底是什么
简介
我们经常会听到甚至需要自己动手去做GC调优。那么GC调优的目的到底是什么呢?让程序跑得更快?让GC消耗更少的资源?还是让程序更加稳定?
带着这些疑问来读一下这篇文章,将会得到一个系统的甚至是不一样的结果。
那些GC的默认值
其实GC或者说JVM的参数非常非常的多,有控制内存使用的:
有控制JIT的:
有控制分代比例的,也有控制GC并发的:
当然,大部分的参数其实并不需要我们自行去调整,JVM会很好的动态帮我们设置这些变量的值。
如果我们不去设置这些值,那么对GC性能比较有影响的参数和他们的默认值有哪些呢?
01
GC的选择
我们知道JVM中的GC有很多种,不同的GC选择对java程序的性能影响还是比较大的。
在JDK9之后,G1已经是默认的垃圾回收器了。
我们看一下G1的调优参数。
G1是基于分代技术的,其实JVM还在开发一些不再基于分代技术的GC算法,比如ZGC,我们可以根据需要来选择适合我们的GC算法。
02
GC的最大线程个数
GC是由专门的GC线程来执行的,并不是说GC线程越多越好,这个默认线程的最大值是由heap size和可用的CPU资源动态决定的。
当然你可以使用下面两个选项来修改GC的线程:
-XX:ParallelGCThreads=threads
设置STW的垃圾收集线程数
-XX:ConcGCThreads = n
设置并行标记线程的数量
一般情况下ConcGCThreads可以设置为ParallelGCThreads的1/4。
03
初始化heap size
默认情况下加初始化的heap size是物理内存的1/64。
你可以使用
-XX:InitialHeapSize=size
来重新设置。
04
最大的heap size
默认情况下最大的heap size是物理内存的1/4。
你可以使用:
-XX:MaxHeapSize
来重新设置。
05
分层编译技术
默认情况下分层编译技术是开启的。你可以使用:
-XX:-TieredCompilation
来关闭分层编译。如果启用了分层编译,那么可能需要关注JIT中的C1和C2编译器带来的影响。
我们到底要什么
鱼,我所欲也,熊掌亦我所欲也;二者不可得兼,舍鱼而取熊掌者也。–孟子
java程序在运行过程中,会发生很多次GC,那么我们其实是有两种统计口径:
平均每次GC执行导致程序暂停的时间(Maximum Pause-Time Goal)。
总的花费在GC上的时间和应用执行时间的比例(Throughput Goal)。
01
最大暂停时间
单次GC的暂停时间是一个统计平均值,因为单次GC的时间其实是不可控的,但是取了平均值,GC就可以动态去调整heap的大小,或者其他的一些GC参数,从而保证每次GC的时间不会超过这个平均值。
我们可以通过设置:
-XX:MaxGCPauseMillis=<nnn>
来控制这个值。
不管怎么设置这个参数,总体需要被GC的对象肯定是固定的,如果单次GC暂停时间比较短,可能会需要减少heap size的大小,那么回收的对象也比较少。这样就会导致GC的频率增加。
从而导致GC的总时间增加,影响程序的Throughput。
02
吞吐率
吞吐率是由花费在GC上的时间和应用程序上的时间比率来决定的。
我们可以通过设置:
-XX:GCTimeRatio=nnn
来控制。
如果没有达到throughput的目标,那么GC可能会去增加heap size,从而减少GC的执行频率。但是这样会增加单次的Maximum Pause-Time。
如果throughput和maximum pause-time的参数同时都设置的话,JVM会去尝试去动态减少heap size的大小,直到其中的一个目标不能满足为止。
相对而言,G1更加偏重于最大暂停时间,而ZGC更加偏重于吞吐率。
更多精彩内容
1 |
JVM系列之:再谈java中的safepoint |
---|---|
2 |
troubleshoot之:使用JFR解决内存泄露 |
3 |
JVM系列之:从汇编角度分析NullCheck |
- 记一次数据库的分析和优化建议(r6笔记第24天)
- linux (ubantu)安装最新版python3.6,以及直接安装anaconda
- 【java基础】匿名类
- 朴素贝叶斯法 2016年11月11日
- 11g中关于控制文件自动备份的改进(r6笔记第22天)
- Java基础(02)-15总结对象数组,集合Collection,集合List
- alert日志中的两种ORA错误分析(r6笔记第21天)
- 通过定制orabbix监控分析潜在的Oracle问题 (r6笔记第32天)
- 【C语言练手】C语言画太极图
- 关于奇怪的并行进程分析(一) (r6笔记第41天)
- 关于ora-02391问题的总结(r6笔记第40天)
- 一次数据库响应慢的问题诊断(r6笔记第39天)
- 贝叶斯分类器及Python实现
- R语言中文分词工具
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 这才是现代C++单例模式简单又安全的实现
- Linux 学习笔记(1) 查看文件内容
- Python从入门到熟练(3):第一个程序
- 数学系的概率论和我们的不太一样。。。
- 如何实现一个优雅的Python的Json序列化库
- 还在从零开始搭建项目?手撸了款快速开发脚手架!
- Node.js 中的 require 是如何工作的?
- Ajax请求携带Cookie
- 关于kubernetes垃圾回收那点事
- 强化学习笔记11:工程师看强化学习
- 强化学习笔记10:经典游戏示例 classic games
- RL实践3——为Agent添加Policy、记忆功能
- 强化学习仿真环境搭建入门Getting Started with OpenAI gym
- 数据分析与数据挖掘 - 04科学计算
- SwiftUI:使用 @EnvironmentObject 从环境中读取自定义值