如何预热Java类以避免第一次调用缓慢?

2022-09-04 23:30:09

我正在做一个项目,我需要所有API调用都少于1秒,但我遇到了一个问题,即第一次调用每个路由比以下路由慢。

目前,第一次调用 /login 需要 3.6 秒,下一次调用需要 170 毫秒,对于所有其他路由也是如此。

我发现在第一次调用时使用它,类被加载到内存中,这导致了性能问题。-XX:+TraceClassLoading

但是,我没有找到一种在启动时加载所有类的简单方法,对于每个新服务,我需要在AppplicationRunner中添加一个预热调用。

有没有人有一个解决方案来自动加载SpringBoot应用程序的类或预热其所有路由?


答案 1

Java的类加载是懒惰的。这意味着一个类只在需要的时候由JVM加载,如果需要的话。

如果你想强迫它热切地加载类,你只需要引用它们。一种方法是循环访问jar内容或类文件以获取类名,然后使用它们来调用 。Class.forName(className)

此外,如果启动时间和性能对于您的用例非常重要,您可能希望提前研究 GraalVM 等编译解决方案,或者降低 JIT 的编译阈值 ()。-XX:CompileThreshold


答案 2

对我来说,你唯一可行的选择是,分布在JEP 310JEP 341JEP 350上,但这很可能需要java-13。我们正在我的工作场所进行内部测试(主要是为了好玩,不会撒谎),到目前为止,结果看起来不错。class data sharing

另一个选项是在应用程序启动时调用终结点 - 如果这是一个选项。同样,对于我们来说,例如:我们使用虚拟数据调用它们几百次以预热代码。但是,与此同时,我们有一些服务是不可能的 - 这就是为什么探索太。CDS


推荐