我正在运行启动多个JVM进程的测试。与在JVM中运行的实际测试时间相比,JVM的摘要启动时间非常重要。我如何加快速度?
我已经使用了“-client”选项,这确实有帮助,但没有我想要的那么多。有没有其他方法,比如预加载一堆JVM并以某种方式重用它们?
答案 0 :(得分:35)
如果您确实想要重用JVM,那么“某种程度上”可能是Nailgun。 Nailgun保持JVM运行,然后使用轻型本机客户端启动特定类并处理控制台io。这对于运行小命令行Java实用程序很有用,但是当它重用时,相同的JVM可以累积状态。
要解决状态累积问题,以运行多个JVM为代价,另一个选项是Drip。 Drip通过正确的类路径和其他JVM选项保留了一个新的JVM保留,因此您可以在需要时快速连接并使用它,然后将其丢弃。 Drip散列JVM选项并存储有关如何以散列值作为名称连接到JVM的信息。
答案 1 :(得分:10)
JVM启动性能可以通过多种方式得到改进:CDS,直接调优,CPU固定和jlink(自JDK 9以来)都是不错的选择。 AOT(JDK 9,仅限Linux)有一些粗略的边缘,但可以调整以帮助小型应用程序。
类数据共享是在1.5版本中为客户端VM开发的,但自从处理HotSpot的所有变种(自8年以来的所有GC)以来已经有了很大改进,在启用时大大提升了启动性能。
CDS始终在32位JRE客户端安装上启用,但可能需要在其他地方启用一些手动步骤:
java -Xshare:dump
以生成CDS共享存档-Xshare:auto
添加到您的命令中以确保其已使用虽然-client
可能会或可能不会实际执行任何操作(许多系统上的JVM并不附带客户端VM - 实际上从9开始都没有),有很多方法可以调整HotSpot服务器JVM表现得更像客户端VM:
-XX:TieredStopAtLevel=1
-XX:CICompilerCount=1
-XX:+UseSerialGC
-Xmx512m
这应足以为短暂运行的小应用程序提升启动速度,但可能会对峰值性能产生非常不利的影响。您当然可以通过禁用可能未使用的功能来进一步实现,例如-XX:-UsePerfData
(禁用使用MXBeans和jvmstat可检索的某些运行时信息)。
jlink是Java 9中提供的一种新工具,允许您构建自定义运行时映像。如果您的控制台应用程序仅使用一小部分JDK模块,则可以使自定义运行时非常小,这可以进一步缩短启动时间。最小图像,仅包含java.base模块,可能会将启动时间提高约10-20ms,具体取决于硬件和其他调整:$JAVA_HOME/bin/jlink --add-modules java.base --module-path $JAVA_HOME/jmods --output jbase
(仅限Linux)Java 9引入了实验AOT compiler,jaotc
,可用于帮助应用程序更快地启动并减少周期。开箱即用它可能会减慢立即启动速度(因为AOT&#39代码是一个共享库,它增加了自己的I / O开销,不支持串行GC ..),但是仔细调整我们已经看到它将小型应用程序的启动时间缩短了15-30%。
CPU固定:在大型系统上,我们已经看到源自套接字之间的缓存一致性流量的效果,并且绑定到单个CPU节点可以大大缩短启动时间。在Linux上,像numactl --cpunodebind=0 $JAVA_HOME/bin/java ...
这样的东西应该可以解决问题。
总而言之,我们能够在短至35毫秒内完成最少的应用程序(JDK 9 GA)。各种启动优化已进入JDK10分支,我现在看到数字低至28ms。
答案 2 :(得分:2)
为什么不在一个JVM中加载所有测试?你能做以下一项或多项吗?
Class.forName()
依次加载每个测试类?如果内存分配相当大,可以通过将JVM内存启动大小指定为与最大可分配内存(-Xms
vs -Xmx
)相同的数字来加快速度,这样可以节省JVM回到操作系统获取更多内存。但是在这种情况下,我认为这不太可能是问题。
答案 3 :(得分:2)
为了增加其他人的说法,下一版本的Java( Java 7 Java 8 Java 9)应该在JVM启动时间中添加新的改进,由于平台的模块化,根据this link。
引用:
模块化的一个好处是 该平台下载量较小, 可能会改善初创企业 性能。记忆力较小 足迹也使重要 特别是性能改进 用于桌面应用程序。
答案 4 :(得分:1)
使用Java 5或更高版本运行测试。 Java 5已经显着缩短了启动时间。
除非你可以重用正在运行的虚拟机,否则你的速度要快得多:预先启动很多虚拟机,然后在每个虚拟机中运行一次测试都不会让你的测试更快。
因此,您需要想办法在单个VM中运行多个测试。
答案 5 :(得分:0)
如果您确实需要为每个测试启动一个单独的VM,那么最好的选择可能是确保您使用Sun提供的最新VM版本之一。启动时间比上一个Java版本减少了很多,并且1.6.0_16,一个简单的“Hello world”程序在我的系统上运行大约需要0.2秒。
如果您的问题是“如何在一个VM中运行更多测试”,那么最简单的方法取决于您使用的是哪个测试框架(如果您不使用框架,则应该考虑这一点)。使用JUnit以及可能是JUnit的ant目标,您可以使用模式来匹配要运行的测试,也可以在测试套件中加入不同的测试类,然后可以在一个VM中运行。