【发布时间】:2009-09-29 08:43:21
【问题描述】:
我正在运行启动多个 JVM 进程的测试。与在 JVM 中运行的实际测试的时间相比,JVM 的摘要启动时间非常重要。如何加快速度?
我已经使用了“-client”选项,这确实有帮助,但没有我想要的那么多。还有其他方法吗,比如预加载一堆 JVM 并以某种方式重用它们?
【问题讨论】:
标签: java performance
我正在运行启动多个 JVM 进程的测试。与在 JVM 中运行的实际测试的时间相比,JVM 的摘要启动时间非常重要。如何加快速度?
我已经使用了“-client”选项,这确实有帮助,但没有我想要的那么多。还有其他方法吗,比如预加载一堆 JVM 并以某种方式重用它们?
【问题讨论】:
标签: java performance
【讨论】:
JVM 启动性能可以通过多种方式提高:CDS、直接调优、CPU pinning 和 jlink(从 JDK 9 开始)都是不错的选择。 AOT(JDK 9,仅限 Linux)有一些粗糙的边缘,但可以调整以帮助小型应用程序。
Class Data Sharing 早在 1.5 版本就为客户端 VM 开发,但自从适用于 HotSpot 的所有变体(自 8 以来的所有 GC)以来已经有了很大改进,启用后显着提升了启动性能。
在 32 位 JRE 客户端安装上始终启用 CDS,但可能需要在其他地方启用一些手动步骤:
java -Xshare:dump 以生成 CDS 共享存档-Xshare:auto 添加到您的命令以确保它被使用虽然-client 可能会或可能不会真正做任何事情(许多系统上的 JVM 不附带客户端 VM - 实际上自 9 以来没有),但有许多方法可以调整 HotSpot 服务器 JVM 以使其行为更像客户端虚拟机:
-XX:TieredStopAtLevel=1
-XX:CICompilerCount=1
-XX:+UseSerialGC
-Xmx512m
这应该足以促进小型短期运行应用程序的启动,但可能会对峰值性能产生非常负面的影响。当然,您可以通过禁用您可能不使用的功能来获得更进一步的信息,例如 -XX:-UsePerfData(禁用一些可使用 MXBeans 和 jvmstat 检索的运行时信息)。
jlink 是 Java 9 中的一个新工具,它允许您构建自定义运行时映像。如果您的控制台应用程序仅使用一小部分 JDK 模块,则可以将自定义运行时做得非常小,这可以进一步缩短启动时间。仅包含 java.base 模块的最小映像,根据硬件和其他调整,启动时间可能会增加约 10-20 毫秒:$JAVA_HOME/bin/jlink --add-modules java.base --module-path $JAVA_HOME/jmods --output jbase
(仅限 Linux)Java 9 引入了实验性的 AOT compiler、jaotc,可用于帮助应用程序更快地启动并减少执行此操作的周期。开箱即用它可能会减慢立即启动(因为 AOT 的代码是一个共享库,它增加了自己的 I/O 开销,不支持串行 GC ..),但是通过仔细调整我们'我们已经看到它将小型应用程序的启动时间减少了 15-30%。
CPU pinning:在大型系统上,我们已经看到了来自套接字之间的缓存一致性流量的影响,并且绑定到单个 CPU 节点可以显着缩短启动时间。在 Linux 上,numactl --cpunodebind=0 $JAVA_HOME/bin/java ... 之类的东西应该可以解决问题。
总而言之,我们能够在短短 35 毫秒内执行最少的应用程序(JDK 9 GA)。各种启动优化已进入 JDK10 分支,我现在看到的数字低至 28 毫秒。
【讨论】:
jaotc 已在 JDK 17 中删除。替代方案是 GraalVM native-image,尽管它也有一些陷阱。
为什么不在一个 JVM 中加载所有测试?您能做到以下一项或多项吗?
Class.forName()依次加载每个类?如果内存分配相当大,它可以通过将 JVM 内存启动大小指定为与最大可分配内存相同的数字(-Xms vs -Xmx)来加快速度,这将节省 JVM 必须返回操作系统以获得更多内存。但是在这种情况下,我认为这不太可能是问题。
【讨论】:
为了补充其他人所说的,Java 的下一个版本(Java 7 Java 8 Java 9)应该在 JVM 启动时间方面增加新的改进,由于平台的模块化,根据this link.
引用:
模块化的一个好处是 该平台是一个较小的下载, 潜在地改善启动 表现。拥有更小的内存 足迹也使显着 性能改进,尤其是 用于桌面应用程序。
【讨论】:
使用 Java 5 或更高版本运行测试。 Java 5 的启动时间显着减少。
除非您可以重用正在运行的虚拟机,否则您不会变得更快:预先启动大量虚拟机,然后在每个虚拟机中运行一个测试不会让您的测试更快。
因此,您需要想办法在单个 VM 中运行多个测试。
【讨论】:
如果您确实需要为每个测试启动一个单独的 VM,那么您最好的选择可能是确保使用 Sun 的最新 VM 版本之一。与上一个 Java 版本相比,启动时间减少了很多,在 1.6.0_16 中,一个简单的“Hello world”程序在我的系统上运行大约需要 0.2 秒。
如果您的问题是“如何在一个 VM 中运行更多测试”,那么最简单的方法取决于您使用的是哪个测试框架(如果您不使用框架,您应该真正考虑一下)。使用 JUnit 和可能的 JUnit 的 ant 目标,您可以使用模式来匹配您想要运行的测试,或者将不同的测试类加入一个测试套件中,然后可以在一个 VM 中运行。
【讨论】: