快速,低成本,低扰动地运行一段Java代码

栏目: Java · 发布时间: 7年前

内容简介:JVM是个运行服务端应用的好VM,但如果你只是想频繁地运行一段Java写的脚本,或者在跑一些辅助性的Java程序比如监控,比如日志收集,这时候的诉求就和平日里的应用不一样了:一、启动快速,动静小。二、低成本,节约CPU、内存和线程。

JVM是个运行服务端应用的好VM,但如果你只是想频繁地运行一段 Java 写的脚本,或者在跑一些辅助性的Java程序比如监控,比如日志收集,这时候的诉求就和平日里的应用不一样了:

一、启动快速,动静小。

二、低成本,节约CPU、内存和线程。

三、低扰动,不干扰主应用的运行。

1. 从失败的取经开始

第一时间,看看jmap,jstack们用了什么参数,结果发现通通只有一个-Xms8m (在它们运行时,跑jps -v 可见,源码级确认JDK7见Makefile.launcher,JDK8见CompileLaunchers.gmk)。

另外,传说中的-client,在多核的 Linux 服务器上的也是无效的。

下面开始自己的折腾,首先给跑的脚本配上"-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime", 在gc.log 里就会有实际启动参数,GC日志,以及结束时打印内存各代的占用。

其次,长期跑一个 pidstat -l 1| grep XXX 监控进程的CPU消耗

最后,jstack一下进程,看看里面跑着多少线程,一个默认的JVM,线程数多得吓人。

2. 类的加载和编译

2.1 -Xverify:none

来自优化Eclipse启动速度的经验,说关闭Java类加载验证可以加快10% -15%的启动速度。

2.2 设定编译级别

JIT编译之后的代码比解释执行字节码更快,更省CPU,但编译本身就需要CPU,也需要额外的编译线程。临时给启动脚本配上 “-XX:+PrintCompilation”,观察编译情况。

如果脚本的代码只简单的跑一次,比如vjtools里的vjmxcli,建议就不要进行JIT编译了,编译完了也用不上,直接解释执行就好。禁止它:-Djava.compiler=NONE

如果脚本会用于循环计算,比如vjtools里的vjmap,则建议打开多层编译,一开始就对运行到的方法进行静态编译,不用等方法被调用1万次。多层编译在JDK8默认打开,显式打开:-XX:+TieredCompilation。

但打开多层编译也会导致程序运行初期有较多的编译任务,吃比较多的CPU,可以显式关掉多层编译 -XX:-TieredCompilation来对比一下,综合其带来的性能提升,脚本的生命周期长短,以及额外的CPU支出来综合评价。

2.3 编译线程的设定

在24核服务器上,默认有4条C1编译线程,8条C2编译线程(多层编译下),考虑到低成本原则,建议把它设到最小的-XX:CICompilerCount=2。

2.4 未来黑科技-AOT

JIT不够酷,预先把代码编译(Ahead-of-Time,AOT) 更好。 JDK9里有一个Hotspot编译器组搞的试验性的jaotc,另一个选择是GraalVM全家桶里带的 SubstrateVM ,这个支持JDK8。两者都是基于Graal,看各位大大炫,但我还没玩过。

3. GC 设置

这些脚本,辅助进程一般不介意GC延时,建议使用吞度量最的串行收集算法 -XX:+UseSerialGC,大大减少了其他GC算法所产生的大量GC线程,保证自己GC时也不会影响到主应用。

如果依然想使用并行算法,就一定要设置GC线程数,如果按默认值,在24核机器上YGC和CMS GC的线程数分别是18和5,一旦发生GC,将占用大量的CPU核,直接对主应用产生巨大的影响。可设为 -XX 快速,低成本,低扰动地运行一段Java代码 arallelGCThreads=2 -XX:ConcGCThreads=1

4. 内存设置

JVM的堆内存扩张并没有想象中那么智能,当-Xms 与 -Xmx 不等,又没有指定新生代比例时,新生代大小更是混乱。建议根据运行后的实际占用及GC日志,完整设置一个最合适的值。

快速运行一次的脚本,老生代几乎没用,新生代可以设大些。

-Xms96m -Xmx96m -Xmn64m

长期运行的,则一般设为1:1。

-Xms256m -Xmx256m -XX:NewRatio=1

每条线程的内存从默认1M回到256k: -xss256k

永久代也可以一设,可惜JDK7/8的参数不兼容,用java -version 拿版本号太贵了,所以如果明确了JDK版本的话可以设置,否则就算了。

5. 其他

这些脚本,免不了和数字打交道,如果不保证没有int ->Integer的autoboxing,就还是打开-XX:AutoBoxCacheMax=20000

如果有其他更多黑科技,请大家补充。

6. 小结

谢谢你看到这里,这篇的题材比较偏门,幽僻处可有人行。

一段快速执行,关闭了JIT的脚本,启动命令大概长这个样子:

-Xms96m -Xmx96m -Xmn64m -Xss256k -XX:+UseSerialGC -Djava.compiler=NONE -Xverify:none -XX:AutoBoxCacheMax=20000

一段辅助程序,启动命令大概长这个样子

-Xms256m -Xmx256m -XX:NewRatio=1 -Xss256k -XX:+UseSerialGC -XX:-TieredCompilation -XX:CICompilerCount=2 -Xverify:none -XX:AutoBoxCacheMax=20000

VJTools 几个 工具 的启动脚本,都按这个标准重写了一下。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法技术手册

算法技术手册

[美]海涅曼 (Heineman.G.T.)、[美]波利切 (Pollice.G.)、[美]塞克欧 (Selkow.S.) / 东南大学出版社 / 2009-4 / 58.00元

创造稳定的软件需要有效的算法,但是程序设计者们很少能在问题出现之前就想到。《算法技术手册(影印版)》描述了现有的可以解决多种问题的算法,并且能够帮助你根据需求选择并实现正确的算法——只需要一定的数学知识即可理解并分析算法执行。相对于理论来说,本书更注重实际运用,书中提供了多种程序语言中可用的有效代码解决方案,可轻而易举地适合一个特定的项目。有了这本书,你可以: 解决特定编码问题或改进现有解决......一起来看看 《算法技术手册》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具