2019独角兽企业重金招聘Python工程师标准>>>

JVM性能调优

1 堆设置调优

年轻代大小选择

  • 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
  • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
    通过-XX:NewRadio设置新生代与老年代的大小比例,通过-Xmn来设置新生代的大小。

年老代大小选择

  • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:

    • 并发垃圾收集信息
    • 持久代并发收集次数
    • 传统GC信息
    • 花在年轻代和年老代回收上的时间比例
  • 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。

  • 较小堆引起的碎片问题
    因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:

    • -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
    • -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩

2 GC策略调优

  1. 能够忍受full gc的停顿?

    是:选择throughput

    否:如果堆较小,使用CMS或者G1;如果堆较大,选择G1

  2. 使用默认配置能达到期望目标吗?

    首先尽量使用默认配置,因为垃圾收集技术在不断发展成熟,自动优化大多数的效果是最好的。如果默认配置没有达到期望,请确认垃圾收集是否是性能瓶颈。如负荷较高的应用,如果垃圾收集上的时间不超过3%,即使进行垃圾回收调优效果也不大。

  3. 应用的停顿时间和预期的目标接近吗?

    是:调整最大停顿时间设定可能是需要做的

    否:需要进行其他调整

    如果停顿时间太长,但是吞吐量正常,可以尝试减少新生代大小(如果是full gc,则减少老年代大小),这样停顿时间变短,但是单次时间变长

  4. GC停顿很短了,但是吞吐量上不去?

    增大堆的大小,但是单次停顿时间会加长

  5. 使用并发收集器,发生了由并发模式失败引发的full gc?

    如果CPU资源充足,可以增加并发GC的线程数数

  6. 使用并发收集器,发生由晋升失败引起的full gc?

    如果是CMS,意味着发生了碎片化,这种情况下:使用跟大的堆;尽早启动后台回收
    如果堆空间较大,可以选择使用G1

3 JIT调优

  1. 一般只需要选择是使用客户端版或者服务器版的JIT编译器即可。
  2. 客户端版的JIT编译器使用:-client指定,服务器版的使用:-server。
  3. 选择哪种类型一般和硬件的配置相关,当然随着硬件的发展,也没有一个确定的标准哪种硬件适合哪种配置。
  4. 两种JIT编译器的区别:
    • Client版对于代码的编译早于Server版,也意味着代码的执行速度在程序执行早期Client版更快。
    • Server版对代码的编译会稍晚一些,这是为了获取到程序本身的更多信息,以便编译得到优化程度更高的代码。因为运行在Server上的程序通常都会持续很久。
  5. Tiered编译的原理:
    • JVM启动之初使用Client版JIT编译器
    • 当HotSpot形成之后使用Server版JIT编译器再次编译
  6. 在Java 8中,默认使用Tiered编译方式。

不过在Java7版本之后,一旦开发人员在程序中显式指定命令“-server”时,缺省将会开启分层编译(Tiered Compilation)策略,由client编译器和server编译器相互协作共同来执行编译任务。不过在早期版本中,开发人员则只能够通过命令“-XX:+TieredCompilation”手动开启分层编译策略。

  • -Xint:完全采用解释器模式执行程序;
  • -Xcomp:完全采用即时编译器模式执行程序;
  • -Xmixed:采用解释器+即时编译器的混合模式共同执行程序。

启动优化

Application -client -server -XX:+TieredCompilation 类数量
HelloWorld 0.08s 0.08s 0.08s Few
NetBeans 2.83s 3.92s 3.07s ~10000
HelloWorld 51.5s 54.0s 52.0s ~20000

总结

  1. 当程序的启动速度越快越好时,使用Client版的JIT编译器更好。
  2. 就启动速度而言,Tiered编译方式的性能和只使用Client的方式十分接近,因为Tiered编译本质上也会在启动是使用Client JIT编译器。

批处理优化

对于批处理任务,任务量的大小是决定运行时间和使用哪种编译策略的最重要因素:

Number of Tasks -client -server -XX:+TieredCompilation
1 0.142s 0.176s 0.165s
10 0.211s 0.348s 0.226s
100 0.454s 0.674s 0.472s
1000 2.556s 2.158s 1.910s
10000 23.78s 14.03s 13.56s

可以发现几个结论:

  1. 当任务数量小的时候,使用Client或者Tiered方式的性能类似,而当任务数量大的时候,使用Tiered会获得最好的性能,因为它综合使用了Client和Server两种编译器,在程序运行之初,使用Client JIT编译器得到一部分编译过的代码,在程序“热点”逐渐形成之后,使用Server JIT编译器得到高度优化的编译后代码。
  2. Tiered编译方式的性能总是好于单独使用Server JIT编译器。
  3. Tiered编译方式在任务量不大的时候,和单独使用Client JIT编译器的性能相当。

总结

  1. 当一段批处理程序需要被执行时,使用不同的策略进行测试,使用速度最快的那一种。
  2. 对于批处理程序,考虑使用Tiered编译方式作为默认选项。

长时间运行应用的优化

对于长时间运行的应用,比如Servlet程序等,一般会使用吞吐量来测试它们的性能。 以下的一组数据表示了一个典型的数据获取程序在使用不同“热身时间”以及不同编译策略时,对吞吐量(OPS)的影响(执行时间为60s):

Warm-upPeriod -client -server -XX:+TieredCompilation
0s 15.87 23.72 24.23
60s 16.00 23.73 24.26
300s 16.85 24.42 24.43

即使当“热身时间”为0秒,因为执行时间为60秒,所以编译器也有机会在次期间做出优化。

从上面的数据可以发现的几个结论:

  1. 对于典型的数据获取程序,编译器对代码编译和优化发生的十分迅速,当“热身时间”显著增加时,如从60秒增加到300秒,最后得到的OPS差异并不明显。
  2. -server JIT编译器和Tiered编译的性能显著优于-client JIT编译器。

总结

  1. 对于长时间运行的应用,总是使用-server JIT编译器或者Tiered编译策略。

代码缓存调优(Tuning the Code Cache)

当JVM对代码进行编译后,被编译的代码以汇编指令的形式存在于代码缓存中(Code Cache),显然这个缓存区域也是有大小限制的,当此区域被填满了之后,编译器就不能够再编译其他Java字节码了。

Code Cache的最大空间可以通过:-XX:ReservedCodeCacheSize=N来进行设置。

4 JVM线程调优

调节线程栈大小

通过设置-Xss参数,在内存比较稀缺的机器上,可以减少线程栈的大小,在32位的JVM上,可以减少线程栈大小,可以稍稍增加堆的可用内存。每个线程默认会开启1M的堆栈,用于存放栈帧、调用参数、局部变量等,对大多数应用而言这个默认值太了,一般256K就足用。

偏向锁

使用-XX:UseBiasedLocking选项来禁用偏向锁,偏向锁默认开启。偏向锁可以提高缓存命中率,但是因为偏向锁也需要一些簿记信息,有时候性能会更糟,比如使用了某些线程池,同步资源或代码一直都是多线程访问的,那么消除偏向锁这一步骤对你来说就是多余的。

自旋锁

使用-XX:UseSpinning参数可以设置自旋锁是否开启,但是Java7以后自旋锁无法禁用。

线程优先级

每个线程都可以由开发人员指定优先级,不过真正执行时的优先级还取决于操作系统为每个线程计算的当前优先级。开发人员不能依赖线程优先级来影响其性能,如果要提高某些任务的优先级,就必须使用应用层逻辑来划分优先级,可以通过将任务指派给不同线程池并修改哪些池子大小来实现。

总结

理解线程如何运作,可以获得很大的性能优势,不过就线程的性能而言,没有太多可以调优的:可以修改的JVM标识相当少,而且效果不明显。

5 典型案例

$JAVA_ARGS
.=
"
-Dresin.home=$SERVER_ROOT
-server
-Xmx3000M
-Xms3000M
-Xmn600M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-Xss256K
-XX:+DisableExplicitGC
-XX:SurvivorRatio=1
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:LargePageSizeInBytes=128M
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
";

说明:

64位jdk参考设置,年老代涨得很慢,CMS执行频率变小,CMS没有停滞,也不会有promotion failed问题,内存回收得很干净

转载于:https://my.oschina.net/weiweiblog/blog/3036188

JVM解读-性能调优实例相关推荐

  1. 2020年薪30W的Java程序员都要求熟悉JVM与性能调优!

    前言 作为Java程序员,你有没有被JVM伤害过?面试的时候是否碰到过对JVM的灵魂拷问? 一.JVM 内存区域划分 1.程序计数器(线程私有) 程序计数器(Program Counter Regis ...

  2. Tomcat 和 JVM 的性能调优总结

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://rrd.me/enKbC Tomcat性能调优 ...

  3. jvm maxgcpausemillis 默认值_Tomcat和JVM的性能调优总结

    Tomcat性能调优: 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创 ...

  4. Android性能调优实例

    本文主要分享自己在appstore项目中的性能调优点,包括 同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等. 一.性能瓶颈点 整个页面主要由6个Page的ViewPager,每个 ...

  5. 第5课:实战演示jvm三大性能调优参数:-xms -xmx -xss

    内容: 1.实战演示-Xss性能调优参数 2.实战演示-Xms.-Xmx性能调优参数 一.实战演示-Xss性能调优参数 Java每个线程的Stack大小.JDK5.0以后每个线程堆栈大小为1M,以前每 ...

  6. 【十四】jvm 性能调优实例

    实例1: POI Excel 导出 Excel对象很大,多人同时登录系统导出Excel的话,就会有多个大Excel对象到老年代,这是老年代需要回收,系统可能会卡顿. jvm堆内存设置的越大,Full ...

  7. zz温故知新:Tomcat调优JVM内存性能调优

    Java性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收,下面会重点介绍这方面) 代码层优化:避免过多循环嵌套.调用和复杂逻辑. Tomcat调优主要内容如下: 1. ...

  8. 【JVM】JVM参数性能调优 -Xms -Xmx -Xmn -XX:NewRatio -XX:SurvivorRatio

    原文链接: http://unixboy.iteye.com/blog/174173/ 上图来自:https://blog.csdn.net/jakeswang/article/details/105 ...

  9. Linux—JVM等性能调优监控

    关注微信公众号:CodingTechWork,一起学习进步. 介绍   在linux上跑程序时,常常遇到程序卡顿,内存消耗大,这时候,我们需要使用free查看内存使用情况及top内存消耗排行,当然,我 ...

最新文章

  1. PMP-【第14章 五大过程组的工作要点】2021-2-17(292页-303页)
  2. 十八、“问余浪子今何在,唯有回头铸梦人”(2021.5.28)
  3. mysql索引列是锁表还是锁行_[转]关于MYSQL Innodb 锁行还是锁表
  4. Slide:配置Oracle 10g双向流复制
  5. .NET面试题系列(七)IIS
  6. 9:14 2009-7-22
  7. Python窗体操作函数
  8. BZOJ 2716: [Violet 3]天使玩偶 | CDQ分治
  9. 2021年1月十大热门报告盘点(5天VIP会员免费送)
  10. 安徽大学java期末_安微大学2017~2018年度期末考试题卷
  11. ajax返回数据类型为XML数据的处理
  12. php随机函数给字加颜色,四种php随机字生成符串的方法
  13. 彻底的卸载SQL Server2005?
  14. 搜索摄像头/录像机IP地址工具是什么
  15. IOS学习之Segue
  16. python pandas按照行数切分文件
  17. (转载) Android RecyclerView 使用完全解析 体验艺术般的控件
  18. 解决 Exception: ROM is missing for pong, see https://github.com/openai/atari-py#roms for instructions
  19. c语言中ifelse意义,c语言if和else if的区别
  20. C语言复习知识点汇总2--计算机二级(C语言)

热门文章

  1. 前沿 | DeepMind 最新研究——神经算术逻辑单元,有必要看一下!
  2. 牛!何恺明包揽2项ICCV 2017最佳论文奖!这位高考状元告诉你什么是开挂的人生
  3. 课程 | 想成为高薪、抢手又能改变世界的机器学习工程师?
  4. HTTP Host 头攻击,是什么鬼?
  5. Lombok经常用,却不知道它的原理是什么
  6. 面试必备:Java线程池解析
  7. GNN教程:Weisfeiler-Leman算法!
  8. 《数据竞赛白皮书·下篇》发布,开源办好一场数据竞赛的实践方法论
  9. Datawhale第四期组队学习团队成员
  10. 中国Nature第一人,居然是清朝的他