java gc测试_Java中垃圾回收器GC对吞吐量的影响测试-程序员宅基地

技术标签: java gc测试  

在看内存管理术语表的时候偶然发现了”Pig in the Python(注:有点像中文里的贪心不足蛇吞象)”的定义,于是便有了这篇文章。表面上看,这个术语说的是GC不停地将大对象从一个分代提升到另一个分代的情景。这么做就好比巨蟒整个吞食掉它的猎物,以至于它在消化的时候都没办法移动了。

在接下来的这24个小时里我的头脑中充斥着这个令人窒息的巨蟒的画面,挥之不去。正如精神病医生所说的,消除恐惧最好的方法就是说出来。于是便有了这篇文章。不过接下的故事我们要讲的不是蟒蛇,而是GC的调优。我对天发誓。

大家都知道GC暂停很容易造成性能瓶颈。现代JVM在发布的时候都自带了高级的垃圾回收器,不过从我的使用经验来看,要找出某个应用最优的配置真是难上加难。手动调优或许仍有一线希望,但是你得了解GC算法的确切机制才行。关于这点,本文倒是会对你有所帮助,下面我会通过一个例子来讲解JVM配置的一个小的改动是如何影响到你的应用程序的吞吐量的。

示例

我们用来演示GC对吞吐量产生影响的应用只是一个简单的程序。它包含两个线程:

PigEater �C 它会模仿巨蟒不停吞食大肥猪的过程。代码是通过往java.util.List中添加 32MB字节来实现这点的,每次吞食完后会睡眠100ms。

PigDigester �C 它模拟异步消化的过程。实现消化的代码只是将猪的列表置为空。由于这是个很累的过程,因此每次清除完引用后这个线程都会睡眠2000ms。

两个线程都会在一个while循环中运行,不停地吃了消化直到蛇吃饱为止。这大概得吃掉5000头猪。

package eu.plumbr.demo;

public class PigInThePython {   static volatile List pigs = new ArrayList();   static volatile int pigsEaten = 0;   static final int ENOUGH_PIGS = 5000;

public static void main(String[] args) throws InterruptedException {     new PigEater().start();     new PigDigester().start();   }

static class PigEater extends Thread {

@Override     public void run() {       while (true) {         pigs.add(new byte[32 * 1024 * 1024]); //32MB per pig         if (pigsEaten > ENOUGH_PIGS) return;         takeANap(100);       }     }   }

static class PigDigester extends Thread {     @Override     public void run() {       long start = System.currentTimeMillis();

while (true) {         takeANap(2000);         pigsEaten+=pigs.size();         pigs = new ArrayList();         if (pigsEaten > ENOUGH_PIGS)  {           System.out.format("Digested %d pigs in %d ms.%n",pigsEaten, System.currentTimeMillis()-start);           return;         }       }     }   }

static void takeANap(int ms) {     try {       Thread.sleep(ms);     } catch (Exception e) {       e.printStackTrace();     }   } }

现在我们将这个系统的吞吐量定义为“每秒可以消化的猪的头数”。考虑到每100ms就会有猪被塞到这条蟒蛇里,我们可以看到这个系统理论上的最大吞吐量可以达到10头/秒。

GC配置示例

我们来看下使用两个不同的配置系统的表现分别是什么样的。不管是哪个配置,应用都运行在一台拥有双核,8GB内存的Mac(OS X10.9.3)上。

第一个配置:

1.4G的堆(-Xms4g -Xmx4g)

2.使用CMS来清理老年代(-XX:+UseConcMarkSweepGC)使用并行回收器清理新生代(-XX:+UseParNewGC)

3.将堆的12.5%(-Xmn512m)分配给新生代,并将Eden区和Survivor区的大小限制为一样的。

第二个配置则略有不同:

1.2G的堆(-Xms2g -Xms2g)

2.新生代和老年代都使用Parellel GC(-XX:+UseParallelGC)

3.将堆的75%分配给新生代(-Xmn 1536m)

4.现在是该下注的时候了,哪个配置的表现会更好一些(就是每秒能吃多少猪,还记得吧)?那些把筹码放到第一个配置上的家伙,你们一定会失望的。结果正好相反:

1.第一个配置(大堆,大的老年代,CMS GC)每秒能吞食8.2头猪

2.第二个配置(小堆,大的新生代,Parellel GC)每秒可以吞食9.2头猪

现在我们来客观地看待一下这个结果。分配的资源少了2倍但吞吐量提升了12%。这和常识正好相反,因此有必要进一步分析下到底发生了什么。

分析GC的结果

原因其实并不复杂,你只要仔细看一下运行测试的时候GC在干什么就能发现答案了。这个你可以自己选择要使用的工具。在jstat的帮助下我发现了背后的秘密,命令大概是这样的:

jstat -gc -t -h20 PID 1s

通过分析数据,我注意到配置1经历了1129次GC周期(YGCT_FGCT),总共花了63.723秒:

Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT

594.0 174720.0 174720.0 163844.1  0.0   174848.0 131074.1 3670016.0  2621693.5  21248.0 2580.9   1006   63.182  116 0.236   63.419

595.0 174720.0 174720.0 163842.1  0.0   174848.0 65538.0  3670016.0  3047677.9  21248.0 2580.9   1008   63.310  117 0.236   63.546

596.1 174720.0 174720.0 98308.0 163842.1 174848.0 163844.2 3670016.0   491772.9  21248.0 2580.9   1010   63.354  118 0.240   63.595

597.0 174720.0 174720.0  0.0   163840.1 174848.0 131074.1 3670016.0   688380.1  21248.0 2580.9   1011   63.482  118 0.240   63.723

第二个配置一共暂停了168次(YGCT+FGCT),只花了11.409秒。

Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT

539.3 164352.0 164352.0  0.0    0.0   1211904.0 98306.0   524288.0   164352.2  21504.0 2579.2 27    2.969  141 8.441   11.409

540.3 164352.0 164352.0  0.0    0.0   1211904.0 425986.2  524288.0   164352.2  21504.0 2579.2 27    2.969  141 8.441   11.409

541.4 164352.0 164352.0  0.0    0.0   1211904.0 720900.4  524288.0   164352.2  21504.0 2579.2 27    2.969  141 8.441   11.409

542.3 164352.0 164352.0  0.0 0.0   1211904.0 1015812.6  524288.0   164352.2  21504.0 2579.2 27 2.969  141 8.441   11.409

考虑到两种情况下的工作量是等同的,因此――在这个吃猪的实验中当GC没有发现长期存活的对象时,它能更快地清理掉垃圾对象。而采用第一个配置的话,GC运行的频率大概会是6到7倍之多,而总的暂停时间则是5至6倍。

说这个故事有两个目的。第一个也是最主要的一个,我希望把这条抽风的蟒蛇赶紧从我的脑海里赶出去。另一个更明显的收获就是――GC调优是个很需要技巧的经验活,它需要你对底层的这些概念了如指掌。尽管本文中用到的这个只是很平常的一个应用,但选择的不同结果也会对你的吞吐量和容量规划产生很大的影响。在现实生活中的应用里面,这里的区别则会更为巨大。因此,就看你如何抉择了,你可以去掌握这些概念,或者,只关注你日常的工作就好了,让Plumbr来找出你所需要的最合适的GC配置吧。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_29144347/article/details/114190286

智能推荐

android+bootanimation+图片格式,Android bootanimation播放mp4的可行性分析-程序员宅基地

文章浏览阅读478次。Android的bootanimation用于控制显示开机的启动动画,但是由于Android源码里只支持一帧一帧的显示图片,从而达到动画的效果, bootanimation本身并不支持播放mp4. 那对于一些对于流畅度要求很高,或者想要做一些非常酷炫的动画效果, bootanimation怕是不行了。那如果把动画效果做成mp4视频,然后在bootanimation里播放,那会不会是一种不错的解决方..._android bootanimation 图片要求

[翔哥高手无敌之路]0-001.项目有多余资源?那就删除吧!-程序员宅基地

文章浏览阅读63次。工具用途程序员在做项目的时候通常会接收到很多资源,如图片、音频等,在项目完成过程中会遭遇诸多需求改动,又会有新的资源被引入项目,等到项目完成的时候会遭遇项目中有很多资源占据空间以至于打出来的包太大,其主要原因就是因为有很多资源根本没有用,却还在res中,这时候就要删除旧的,没用的资源以达到减小包大小的目的。接下来要介绍的这款工具就是基于这种情况下被开发出来的,方便程序员不用一个个目录..._翔哥网络技术工作室

LeetCode-有效的括号(C++)_leetcode有效的括号c++-程序员宅基地

文章浏览阅读780次。题目描述:给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。注意空字符串可被认为是有效字符串。示例 1:输入: “()”输出: true示例 2:输入: “()[]{}”输出: true示例 3:输入: “(]”输出: false示例 4:输入..._leetcode有效的括号c++

ngrok实现内网穿透,让家里的笔记本也能做服务器_笔记本内网穿透-程序员宅基地

文章浏览阅读909次。背景家里淘汰了一台笔记本,windows系统装起来很卡,于是装了个linux系统。这台笔记本有2G内存,奔腾双核处理器,配置比我在阿里云上买的ECS高多了,于是想着给它利用起来。研究了一下,发现ngrok内网穿透能实现这个功能,刚好我也有外网服务器和域名,那就直接开干。安装gcc、git和go语言yum install gcc -y yum install git -yyum inst..._笔记本内网穿透

signature=e7b038f264f5a1cf5b8e81732b377b41,不同养生功法对2型糖尿病伴失眠患者抑郁,焦虑和睡眠质量的影响...-程序员宅基地

文章浏览阅读160次。摘要:目的:观察中医不同养生功法对2型糖尿病伴失眠患者抑郁,焦虑情绪和睡眠质量的影响.方法:将90例广安门医院内分泌门诊和睡眠门诊就诊的2型糖尿病伴失眠患者随机分为八段锦组,六字诀组和对照组三组,每组30人.八段锦组在常规治疗基础上采用八段锦和放松功进行干预,六字诀组在常规治疗基础上采用六字诀和放松功进行干预,对照组进行常规治疗,不加气功干预.所有入组患者在治疗前,治疗2个月,治疗4个月分别测量匹..._京程气67ee8f

前端webpack5+打包工具基础入门css压缩babel配置ES6代码转ES5搭建简单的线上环境完整流程(一)_前端es5项目如何线上运行-程序员宅基地

文章浏览阅读860次。所需软件:vscode,官网链接下载:https://code.visualstudio.com/;(也可以用自己习惯的编辑器)node.js,官网链接下载:http://nodejs.cn/;使用chrome浏览器时遇到英文网站可以点击右键翻译安装自己电脑的合适版本即可。安装这些一般直接点击下一步即可,对于一些国外的软件注意安装目录中最好不要有中文路径,以免出现问题。1.创建一个webpackdome文件夹首先我们创建一个webpackdome文件夹,然后把该文件夹拖入之我们的编辑器(vsc_前端es5项目如何线上运行

随便推点

【数据分享】1999—2021年地级市各类交通工具的客货运量和拥有量数据(Shp/Excel格式)-程序员宅基地

文章浏览阅读137次。【数据分享】1999—2021年地级市各类交通工具的客货运量和拥有量数据(Shp/Excel格式)

SQL SERVER 2008安装教程_sql server 2008 enterprise-程序员宅基地

文章浏览阅读548次。本篇文章介绍了安装SQL Server 2008企业版的软硬件配置要求,安装过程的详细步骤,以及需要注意的事项。安装步骤(1). 在安装文件setup.exe上,单击鼠标右键选择“以管理员的身份运行”,如下图所示:(2). 打开如下所示的”SQL Server安装中心”对话框:(3). 选择左边的安装选项,单击右边的“全新SQL Server独立安装或向现有安装添加功能”选项,如图所示:(4). 在打开”SQL Server 2008安装程序“对话框中,出现“安装程序支持规则” 选项,可以看到,一些_sql server 2008 enterprise

Flutter 环境搭建以及填坑指南(Win10 系统且已有 Android 开发环境 )-程序员宅基地

文章浏览阅读2.1k次。地址 https://flutter.io/docs/get-started/install/windows中文教程地址 https://flutterchina.club/setup-windows/需要下载 git ,下载地址 git for win,安装完成之后需要 配置环境变量。获取 Flutter SDK,推荐使用 git clone 的方式如我想将安装目录放在C...

常见开源监控工具的简单介绍(Prometheus、Zabbix、Nagios、Open-Falcon)-程序员宅基地

文章浏览阅读8.1k次,点赞2次,收藏10次。Prometheus是由Go语言开发的,一款开源的监控、报警、时间序列数据库的组合。2016年,Prometheus被纳入了CNCF云原生基金会(Cloud Native Computing Foundation),成为仅次于Kubernetes的第二大开源项目。时间序列数据(TimeSeries Data):按照时间顺序记录系统、设备状态编号的数据,称为时序数据。

vue使用vue-awesome-swiper插件结合animate.css_vue swiper 使用animate-程序员宅基地

文章浏览阅读3k次。在前端使用swiper很多人都能想到使用swpier(网址: https://www.swiper.com.cn/), swiper能兼容很多不同的项目,如vue、react、原声html等。当你使用swipe时会发现每次使用都需要创建一个swiper对象,因此vue的生态系统中封装了vue-awesome-swiper插件,具体使用如下:1、下载vue-awesome-swiper插件n..._vue swiper 使用animate

2022数学建模高教杯国家一等奖经验分享_2022年数学建模全国一等奖下载-程序员宅基地

文章浏览阅读1.5k次,点赞7次,收藏9次。2022数学建模高教杯国家一等奖经验分享_2022年数学建模全国一等奖下载

推荐文章

热门文章

相关标签