short-运行 Java CLI 应用程序的性能

Performance of short-running Java CLI application

我正在构建一个 java CLI 实用程序来处理文件中的一些数据。

除了从文件中读取外,所有操作都在内存中完成。内存处理部分花费的时间出奇地长,所以我尝试对其进行分析,但无法查明任何执行特别糟糕的特定功能。

我担心 JIT 无法在单个 运行 期间优化程序,所以我用所有程序逻辑对函数的连续执行之间的 运行时间变化进行了基准测试(包括读取输入文件)果然,内存处理部分的 运行 时间在几次执行后下降了,并且在第 5 次 运行.[=12= 时几乎减少了 10 倍]

我尝试在每次执行前打乱输入数据,但没有任何明显的效果。我不确定是否某些缓存可能对这种改进或在程序 运行 期间完成的 JIT 优化负责,但由于通常程序 运行 一次,它总是显示最差的性能。

是否有可能在第一个 运行 期间以某种方式获得良好的表现?是否有通用的方法来优化短期 运行 宁 java 应用程序的性能?

您可能无法通过更改应用程序来优化启动时间和性能1、2。尤其是对于小型应用程序3。而且我当然不认为有“通用”的方法可以做到这一点;即适用于所有情况的优化。

但是,有几个 JVM 特性应该提高短期 JVM 的性能。

Class 数据共享 (CDS) 是一项功能,它允许 JIT 编译 类 缓存在文件系统中(作为 CDS 存档),然后由 运行s 你的应用程序。此功能从 Java 5 开始可用(尽管在早期的 Java 版本中有限制)。

使用 -Xshare JVM 选项控制 CDS 功能。

  • -Xshare:dump 在 运行
  • 期间生成 CDS 存档
  • -Xshare:off -Xshare:on-Xshare:auto 控制是否使用现有的 CDS 存档。

另一种缩短 HotSpot JVM 启动时间的方法是(曾经)使用提前 (AOT) 编译。基本上,您使用 jaotc 命令将应用程序编译为本机代码二进制文件,然后 运行 它生成的可执行文件而不是 java 命令。 jaotc 命令是实验性的,在 Java 9.

中引入

jaotc 似乎未包含在 Oracle 发布的 Java 16 个版本中,并计划在 Java 17 中删除。(参见 JEP 410: Remove the Experimental AOT and JIT Compiler) .

当前为 Java 获取 AOT 编译的推荐方法是使用 GraalVM AOT Java compiler.


1 - 您可以转换为客户端-服务器应用程序,其中服务器始终处于“运行”状态。但是,这还有其他问题,并没有消除客户端的启动时间问题......假设在 Java.
中编码 2 - 根据 @apangin,还有一些其他的应用程序调整可能会使您的代码更加 JIT 友好,但这取决于您的代码当前在做什么。
3 - 可以想象,大型(长 运行ning)单片应用程序的启动时间可以通过重构来改进,以便仅在需要时加载和初始化应用程序的子系统。但是,这听起来并不适合您的用例。

您可以将小型处理 运行 作为一项服务:当您需要 运行 它时,“只需”对该服务进行网络调用(如果它是 HTTP 则更容易,因为很容易Java 中的方法)。那样的话,处理本身就在同一个 JVM 中,并且在 JIT 启动时最终会变得更快。

当然,因为它可能需要大量开发,所以只有在处理本身时才有效:

  • 经常被调用
  • 具有易于传递给服务的参数(通常序列化为字符串)
  • 具有不需要太多数据即可传递给服务的参数(例如几 MB 二进制内容)