jvm调优之分层编译

1 问题

     最近,在某个高QPS的服务在重启的时候,如图1.1所示,重启会load 非常高,出现尖刺,短信报警CPU使用率过高,然后一段时间负载就降下来。搜索下网络的文章,启动后高负载的原因大致是由于启动,随着代码的执行,jvm的jit编译器会将部分热点代码编译为目标机器代码,这时产生的编译线程会占用大量的cpu 导致系统负载高。但是通过top -H -p 查看编译线程的cpu 使用率,发现cpu 使用率比其他线程略高,但是没有明显差距,但是比较其他的请求线程,加在一起的cpu 使用率还是很可观。所以在此怀疑,JIT编译器需要代码执行一定的频率才会进行编译优化,系统刚启动的时候大部分的代码只是解释执行,解释执行的性能比编译执行的性能当然要差很多,所以系统的负载高,等到主要热点代码都是编译执行,系统负载就降下来。 那接下来如何对这个问题调优呢?


图1.1



2  jvm  调优

  针对上面的问题,有两个解决方案:

  2.1 纯编译执行(-Xcomp)

     jvm提供了一个参数-Xcomp ,这个参数可以使jvm运行在纯编译的模式,所有的方法在第一次调用的时候就会编成机器代码,但是现实的话,设置了这个参数之后系统启动负载的确没有上升,这验证了我们之前的猜测,但是随之而来的问题,启动的时间是原来的两倍多,这对我们的应用是不好接受的,现在我们应用启动时间都快到3分钟。所以纯编译不是我们的最优选择。不过,我们还有分层编译。

2.2 分层编译(-XX:+TieredCompilation)

     除了纯编译和默认的mixed之外,jvm 从jdk6u25 之后,引入了分层编译。HotSpot 内置两种编译器,分别是client启动时的c1编译器和server启动时的c2编译器,c2在将代码编译成机器代码的时候需要搜集大量的统计信息以便在编译的时候进行优化,因此编译出来的代码执行效率比较高,代价是程序启动时间比较长,而且需要执行比较长的时间,才能达到最高性能;与之相反, c1的目标是使程序尽快进入编译执行的阶段,所以在编译前需要搜集的信息比c2要少,编译速度因此提高很多,但是付出的代价是编译之后的代码执行效率比较低,但尽管如此,c1编译出来的代码在性能上比解释执行的性能已经有很大的提升,所以所谓的分层编译,就是一种折中方式,在系统执行初期,执行频率比较高的代码先被c1编译器编译,以便尽快进入编译执行,然后随着时间的推移,执行频率较高的代码再被c2编译器编译,以达到最高的性能。

3 效果

  线上环境一台机器加入分层编译参数-XX:+TieredCompilation之后,如图3.1效果很明显,在大多数情况下启动之后负载都不会升高,有时候即使有会升高,也比默认的恢复快很多。


图3.1


作者:worldcbf
链接:https://www.jianshu.com/p/318617435789
來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。






<think>好的,我现在需要帮助用户在Windows系统下进行JVM性能的参数配置最佳实践。首先,我得回忆一下JVM的基础知识,尤其是参数设置的关键点。用户提到了几个引用,可能需要结合这些资料来构建答案。 首先,用户给出的引用中,引用[1]详细介绍了-Xms、-Xmx、-Xmn、-Xss这些参数的作用,这些是的基础。我需要确保在回答中涵盖这些核心参数的正确配置。然后,引用[3]提到分层编译(tiered compilation),在JDK8中默认启用,这可能影响性能,所以需要提到相关的参数,比如-XX:+UseConcMarkSweepGC或者G1GC的选择。 接下来,引用[4]中的案例说明整堆内存可能引发其他问题,比如直接内存溢出。这时候需要提醒用户注意堆外内存的使用情况,比如NIO的DirectByteBuffer,可能需要整-XX:MaxDirectMemorySize参数。 用户的问题是关于Windows系统下的最佳实践,虽然大部分JVM参数是跨平台的,但可能有些特定于Windows的考虑,比如线程栈大小(-Xss)在Windows上的默认值可能与Linux不同,或者垃圾回收器在Windows上的表现差异。比如,在Windows上,默认的并行GC可能不如G1高效,尤其是在处理大堆内存时,可能需要推荐G1。 然后,我需要组织回答的结构,按照步骤来:首先设置堆内存参数,然后选择垃圾回收器,线程栈,处理元空间和直接内存,最后是其他化参数和工具使用。每个部分都需要结合引用中的信息,确保建议有依据。 例如,在堆内存设置中,引用[1]建议将-Xms和-Xmx设为相同值以避免动态整的开销,这应该是基础建议。对于新生代大小,使用-Xmn来设定,但需要根据应用特点整,比如偏向吞吐量还是低延迟。 垃圾回收器的选择方面,引用[3]提到的分层编译可能影响JIT行为,但更直接的是垃圾回收器的选择。对于JDK8,CMS可能还是常用的,但G1在更大堆内存下表现更好,尤其是在Windows上,可能需要根据应用暂停时间的要求来选择。如果用户的应用需要低延迟,G1或之后的ZGC可能更合适,但需要确认JDK版本是否支持。 关于元空间,需要提到-XX:MetaspaceSize和-XX:MaxMetaspaceSize,避免元空间动态扩展导致Full GC。引用[4]中的例子显示堆内存整可能影响其他区域,比如直接内存,所以需要监控堆外内存使用情况,并整MaxDirectMemorySize。 工具方面,需要推荐JDK自带的工具,如jvisualvm和jconsole,以及命令行工具jstat、jmap等,帮助用户监控GC情况和内存使用。 最后,的最佳实践应该是基于监控和迭代测试,而不是一次性设置。需要提醒用户进行压力测试,分析日志,逐步整参数。同时,注意Windows系统本身的内存管理,确保系统有足够资源,避免交换(swapping)影响性能。 可能还需要检查是否有遗漏的参数,比如禁用偏向锁(-XX:-UseBiasedLocking)在高并发场景下的影响,或者整并行GC线程数(-XX:ParallelGCThreads)根据CPU核心数设置。 总结步骤: 1. 设定堆内存参数(-Xms, -Xmx, -Xmn)。 2. 选择合适的垃圾回收器(G1或CMS)。 3. 线程栈大小(-Xss)和元空间参数。 4. 监控和整堆外内存。 5. 其他化参数,如编译选项、并行线程数。 6. 使用工具验证和持续监控。 需要确保每个建议都有引用支持,比如引用[1]和[3]中的参数说明,引用[4]中的问题案例。同时,生成的相关问题要涵盖的不同方面,如参数解析、工具使用、问题排查等。</think>### Windows系统JVM参数配置最佳实践 #### 1. **堆内存配置** - **核心参数** - `-Xms` 和 `-Xmx`:设置初始堆大小和最大堆大小,建议设为相同值以避免动态整的性能开销。例如: ```bash -Xms4g -Xmx4g ``` 根据应用需求整,通常不超过物理内存的50%[^1]。 - `-Xmn`:新生代大小,建议为堆的1/3到1/4。例如: ```bash -Xmn2g ``` 新生代过小会增加Minor GC频率,过大会延长单次GC时间[^1]。 #### 2. **垃圾回收器选择** - **G1垃圾回收器(推荐)** 适合大内存和低延迟场景,JDK9+默认,JDK8需显式启用: ```bash -XX:+UseG1GC ``` - **CMS回收器(备用)** 适用于低延迟但堆内存较小的场景: ```bash -XX:+UseConcMarkSweepGC ``` #### 3. **线程栈与元空间** - **线程栈大小(-Xss)** Windows默认1MB,若线程数多可适当降低,但需避免栈溢出: ```bash -Xss256k ``` - **元空间配置** 避免元空间动态扩容触发Full GC: ```bash -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m ``` #### 4. **堆外内存化** - 若使用NIO直接内存(如Netty),需限制最大直接内存: ```bash -XX:MaxDirectMemorySize=512m ``` 避免因堆外内存溢出导致`java.lang.OutOfMemoryError`[^4]。 #### 5. **其他关键参数** - **禁用偏向锁**(高并发场景): ```bash -XX:-UseBiasedLocking ``` - **并行GC线程数**(根据CPU核心数整): ```bash -XX:ParallelGCThreads=4 ``` - **分层编译化**(JDK8默认启用): ```bash -XX:+TieredCompilation ``` 结合Client和Server模式提升启动与运行性能[^3]。 #### 6. **监控与验证工具** - **VisualVM** 或 **JConsole**:实时监控堆、线程、GC状态。 - **GC日志分析**: ```bash -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps ``` - **命令行工具**: - `jstat -gc <pid>`:查看GC统计。 - `jmap -heap <pid>`:分析堆内存分布。 #### 7. **步骤建议** 1. **基线测试**:记录默认参数下的性能指标(如吞吐量、GC暂停时间)。 2. **逐步整**:每次仅修改1-2个参数,对比化效果。 3. **压力测试**:使用工具(如JMeter)模拟高负载场景。 4. **日志分析**:重点关注Full GC频率和OOM异常。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值