最小化Java“预热”时间的技术或实用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1481853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Technique or utility to minimize Java "warm-up" time?
提问by noahlz
I am supporting a Java messaging application that requires low latency (< 300 microseconds processing each message). However, our profiling shows that the Sun Java Virtual Machine runs slowly at first, and speeds up after the first 5,000 messages or so. The first 5,000 messages have latency of 1-4 milliseconds. After about the first 5,000, subsequent messages have ~250 microseconds latency, with occasional outliers.
我正在支持一个需要低延迟(< 300 微秒处理每条消息)的 Java 消息传递应用程序。但是,我们的分析显示 Sun Java 虚拟机最初运行缓慢,在前 5,000 条左右的消息之后加速。前 5,000 条消息的延迟为 1-4 毫秒。在大约前 5,000 条之后,后续消息有大约 250 微秒的延迟,偶尔会出现异常值。
It's generally understood that this is typical behavior for a Java application. However, from a business standpoint it's not acceptable to tell the customer that they have to wait for the JVM to "warm-up" before they see the performance they demand. The application needs to be "warmed-up" before the first customer message is processed
众所周知,这是 Java 应用程序的典型行为。但是,从业务角度来看,告诉客户他们必须等待 JVM“预热”才能看到他们需要的性能是不可接受的。应用程序需要在处理第一条客户消息之前“预热”
The JVM is Sun 1.6.0 update 4.
JVM 是 Sun 1.6.0 update 4。
Ideas for overcoming this issue:
克服这个问题的想法:
- JVM settings, such as -XX:CompileThreshold=
- Add a component to "warm-up" the application on startup, for example by sending "fake messages" through the application.
- Statically load application and JDK classes upon application startup, so that classes aren't loaded from JARs while processing customer messages.
- Some utility or Java agent that accomplishes either or both of the above two ideas, so that I don't have to re-invent the wheel.
- JVM 设置,例如 -XX:CompileThreshold=
- 添加一个组件以在启动时“预热”应用程序,例如通过应用程序发送“假消息”。
- 在应用程序启动时静态加载应用程序和 JDK 类,以便在处理客户消息时不会从 JAR 加载类。
- 一些实用程序或 Java 代理可以实现上述两个想法中的一个或两个,这样我就不必重新发明轮子了。
NOTE: Obviously for this solution I'm looking at all factors, including chip arch, disk type and configuration and OS settings. However, for this question I want to focus on what can be done to optimize the Java application and minimize "warm up" time.
注意:显然对于这个解决方案,我正在考虑所有因素,包括芯片架构、磁盘类型和配置以及操作系统设置。但是,对于这个问题,我想重点讨论如何优化 Java 应用程序并最大限度地减少“预热”时间。
采纳答案by NawaMan
"Warm-up" in Java is generally about two things:
Java 中的“热身”通常是关于两件事:
(1): Lazy class loading: This can be work around by force it to load.
(1):延迟类加载:这可以通过强制加载来解决。
The easy way to do that is to send a fake message. You should be sure that the fake message will trigger all access to classes. For exmaple, if you send an empty message but your progrom will check if the message is empty and avoid doing certain things, then this will not work.
最简单的方法是发送假消息。您应该确保假消息将触发对类的所有访问。例如,如果您发送一条空消息,但您的程序将检查消息是否为空并避免做某些事情,那么这将不起作用。
Another way to do it is to force class initialization by accessing that class when you program starts.
另一种方法是通过在程序启动时访问该类来强制类初始化。
(2): The realtime optimization: At run time, Java VM will optimize some part of the code. This is the major reason why there is a warm-up time at all.
(2):实时优化:在运行时,Java VM会优化部分代码。这是有预热时间的主要原因。
To ease this, you can sent bunch of fake (but look real) messages so that the optimization can finish before your user use it.
为了缓解这种情况,您可以发送一堆虚假(但看起来是真实的)消息,以便优化可以在您的用户使用之前完成。
Another that you can help to ease this is to support inline such as using private and final as much as you can. the reason is that, the VM does not need to look up the inheritance table to see what method to actually be called.
您可以帮助缓解此问题的另一个方法是支持内联,例如尽可能多地使用 private 和 final。原因是,VM 不需要查找继承表来查看实际调用什么方法。
Hope this helps.
希望这可以帮助。
回答by Aaron Digulla
Your problem is not class loading but "just in time" compilation.
您的问题不是类加载,而是“及时”编译。
Try -XX:CompileThreshold=1
尝试 -XX:CompileThreshold=1
That will force Java to compile everything the first time it runs it. It will slow down the startup of your code somewhat but not VM code (since that gets compiled when Java is installed). There is a bug open to allow Java to compile custom JARs in a similar way and save the result for later executions which would greatly reduce this overhead but there is no pressure to fix this bug any time soon.
这将强制 Java 在第一次运行时编译所有内容。它会稍微减慢代码的启动速度,但不会减慢 VM 代码的速度(因为在安装 Java 时会编译)。有一个 bug open 允许 Java 以类似的方式编译自定义 JAR 并将结果保存以供以后执行,这将大大减少这种开销,但很快就没有修复这个 bug 的压力。
A second option would be to send 5'000 fake messages to the app to "warm it up". Sell this as "making sure everything is set up correctly".
第二种选择是向应用程序发送 5'000 条假消息以“预热”。将此称为“确保一切设置正确”。
[EDIT] Some background info in precompiling classes: Class Data Sharing
[编辑] 预编译类中的一些背景信息:类数据共享
You may want to try IBM's version of Java since here, you can add more classes to the shared pool: Overview of class data sharing
您可能想尝试 IBM 的 Java 版本,因为在这里,您可以向共享池添加更多类:类数据共享概述
[EDIT2]To answer concerns raised by kittylyst: It's true that this will quickly fill up your code cache with methods that are used only once. And it might even make your whole app slower.
[EDIT2]回答kittylyst提出的问题:确实,这将使用仅使用一次的方法快速填满您的代码缓存。它甚至可能会使您的整个应用程序变慢。
If you set it to a low value, the startup time of your application can become horribly slow. This is because the JIT optimization + running the compiled code is more expensive than running the code once in interpreted mode.
如果将其设置为较低的值,应用程序的启动时间会变得非常缓慢。这是因为 JIT 优化 + 运行编译后的代码比在解释模式下运行一次代码更昂贵。
The main problem here is that the code is still compiled "just in time". As long as you can't run every method that you need at least once, the app will "hickup" for a few milliseconds every time it encounters something that hasn't been compiled before.
这里的主要问题是代码仍然是“及时”编译的。只要您不能至少运行一次您需要的每个方法,应用程序将在每次遇到以前未编译过的内容时“停止”几毫秒。
But if you have the RAM, your app is small or you can increase the size of the code cache and you don't mind the slow startup time, you can give this a try. Generally, the default setting is pretty good.
但是如果你有 RAM,你的应用程序很小,或者你可以增加代码缓存的大小,并且你不介意缓慢的启动时间,你可以试试这个。通常,默认设置非常好。
回答by Jesper
Are you using the client or the server JVM? Try starting your program with:
您使用的是客户端还是服务器 JVM?尝试使用以下命令启动您的程序:
java -server com.mycompany.MyProgram
When running Sun's JVM in this mode, the JIT will compile the bytecode to native code earlier; because of this, the program will take longer to start, but it will run faster after that.
在这种模式下运行 Sun 的 JVM 时,JIT 会提前将字节码编译为本地代码;正因为如此,程序将需要更长的时间才能启动,但之后它会运行得更快。
Reference: Frequently Asked Questions About the Java HotSpot VM
Quote:
引用:
What's the difference between the -client and -server systems?
These two systems are different binaries. They are essentially two different compilers (JITs)interfacing to the same runtime system. The client system is optimal for applications which need fast startup times or small footprints, the server system is optimal for applications where the overall performance is most important. In general the client system is better suited for interactive applications such as GUIs. Some of the other differences include the compilation policy,heap defaults, and inlining policy.
-client 和 -server 系统之间有什么区别?
这两个系统是不同的二进制文件。它们本质上是两个不同的编译器 (JIT),它们连接到同一个运行时系统。客户端系统最适合需要快速启动时间或占用空间小的应用程序,服务器系统最适合需要整体性能最重要的应用程序。一般来说,客户端系统更适合于交互式应用程序,例如 GUI。其他一些差异包括编译策略、堆默认值和内联策略。
回答by NawaMan
Seems like your project would benefit from real time guarantees:
似乎您的项目将受益于实时保证:
See: Real Time Java
请参阅:实时 Java
回答by Andriy Plokhotnyuk
If running in Hotspot's server mode on contemporary hardware (with 2 or more cores per CPU) and with latest version of JDK then following option can be used for speeding of warming up:
如果在现代硬件(每个 CPU 具有 2 个或更多内核)和最新版本的 JDK 上以 Hotspot 的服务器模式运行,则可以使用以下选项来加速预热:
-server -XX:+TieredCompilation
回答by kittylyst
Just run a bunch of no-op messages through the system before it's opened for genuine customer traffic. 10k messages is the usual number.
在为真正的客户流量开放之前,只需通过系统运行一堆无操作消息。10k 消息是通常的数字。
For financial apps (e.g. FIX), this is often done by sending orders (at a price far away from last night's close, just in case) to the market before it opens. They'll all get rejected, but that doesn't matter.
对于金融应用程序(例如 FIX),这通常是通过在开盘前向市场发送订单(以远离昨晚收盘价的价格,以防万一)来完成的。他们都会被拒绝,但这没关系。
If the protocol you're using is homebrew, then the next time you upgrade the libraries for it, add explicit support for a "WARMUP" or "TEST" or "SANITYCHECK" message type.
如果您使用的协议是自制协议,那么下次为它升级库时,添加对“WARMUP”或“TEST”或“SANITYCHECK”消息类型的明确支持。
Of course, this likely won't compile up your application-logic-specific pathways, but in a decent messaging app, the part dealing with network traffic will almost certainly be the dominant part of the stack, so that doesn't matter.
当然,这可能不会编译您的特定于应用程序逻辑的路径,但是在一个不错的消息传递应用程序中,处理网络流量的部分几乎肯定会是堆栈的主要部分,所以这无关紧要。
回答by mark
Old thread, I know, but I found this in the internet:
旧线程,我知道,但我在互联网上找到了这个:
A very interesting thing is the influence of option-XX:CompileThreshold=1500 to SUN HotSpot JVM. The default is 10000 for Server VM and 1500 for Client VM. However setting it to 1500 for Server VM makes it faster than Client VM. Setting it to 100 actualy lowers the performance. And using option-Xcomp (which means that all code is compiled before usage) gives even lower performance, which is surprising.
一个很有趣的事情是选项-XX:CompileThreshold=1500 对SUN HotSpot JVM 的影响。服务器 VM 的默认值为 10000,客户端 VM 的默认值为 1500。但是,对于服务器 VM 将其设置为 1500 使其比客户端 VM 更快。将其设置为 100 实际上会降低性能。并且使用选项-Xcomp(这意味着所有代码在使用之前都被编译)会导致更低的性能,这令人惊讶。
Now you know what to do.
现在你知道该怎么做了。