代码之家  ›  专栏  ›  技术社区  ›  noahlz

最小化Java“预热”时间的技术或实用程序?

  •  37
  • noahlz  · 技术社区  · 16 年前

    我支持一个Java消息应用程序,它需要低延迟(300微秒处理每个消息)。然而,我们的分析表明,Sun Java虚拟机首先运行缓慢,并且在前5000个消息之后加速。前5000条消息的延迟为1-4毫秒。大约在前5000条消息之后,后续消息的延迟时间约为250微秒,偶尔会出现异常值。

    一般理解,这是Java应用程序的典型行为。但是,从业务的角度来说,告诉客户他们必须等待JVM“预热”,然后才能看到他们需要的性能是不可接受的。在处理第一条客户消息之前,需要对应用程序进行“预热”

    JVM是Sun 1.6.0更新4。

    克服这个问题的想法:

    1. JVM设置,如-xx:compileThreshold=
    2. 在启动时向应用程序“预热”添加组件,例如通过应用程序发送“假消息”。
    3. 在应用程序启动时静态加载应用程序和JDK类,这样在处理客户消息时就不会从JAR中加载类。
    4. 一些实用工具或Java代理完成上述两个概念中的一个或两个,这样我就不用再发明轮子了。

    注:显然,对于这个解决方案,我会考虑所有因素,包括芯片架构、磁盘类型和配置以及操作系统设置。然而,对于这个问题,我想集中精力做些什么来优化Java应用程序并最小化“热身”时间。

    7 回复  |  直到 13 年前
        1
  •  30
  •   NawaMan    15 年前

    爪哇的“热身”通常有两件事:

    (1):延迟类加载:这可以通过强制加载来解决。

    这样做的简单方法是发送一条假消息。您应该确保假消息将触发对类的所有访问。对于exmaple,如果您发送一条空消息,但是您的程序将检查消息是否为空,并避免执行某些操作,那么这将不起作用。

    另一种方法是在程序启动时通过访问类来强制初始化类。

    (2)实时优化:在运行时,Java VM将优化代码的某些部分。这就是为什么有一个预热时间的主要原因。

    为了缓解这个问题,您可以发送大量假消息(但看起来是真实的),这样优化就可以在用户使用它之前完成。

    另一个可以帮助您缓解这一问题的方法是支持内联,例如尽可能多地使用私有和最终版本。原因是,VM不需要查找继承表来查看实际要调用的方法。

    希望这有帮助。

        2
  •  14
  •   Community Mohan Dere    8 年前

    您的问题不是类加载,而是“及时”编译。

    尝试 -XX:CompileThreshold=1

    这将迫使Java在第一次运行时编译所有的东西。它会稍微降低代码的启动速度,但不会降低VM代码(因为在安装Java时会编译)。有一个漏洞允许Java以类似的方式编译定制的JAR,并将结果保存在以后的执行中,这将大大减少开销,但是没有任何压力来很快修复这个bug。

    第二种选择是向应用程序发送5000条假消息来“预热”。将其作为“确保所有设置正确”出售。

    [编辑]预编译类中的一些背景信息: Class Data Sharing

    您可能想尝试IBM的Java版本,因为在这里,您可以向共享池添加更多类: Overview of class data sharing

    [编辑2] 回答 kittylyst :这确实会很快用只使用一次的方法填满代码缓存。它甚至可能使你的整个应用程序变慢。

    如果将其设置为较低的值,应用程序的启动时间可能会变得非常慢。这是因为运行编译代码的JIT优化+比在解释模式下运行一次代码的成本更高。

    这里的主要问题是代码仍然是“及时”编译的。只要你不能运行每一个你需要的方法至少一次,应用程序将“打嗝”几毫秒,每次遇到一些尚未编译过的东西。

    但是如果你有RAM,你的应用程序很小,或者你可以增加代码缓存的大小,你不介意启动时间太慢,你可以尝试一下。一般来说,默认设置相当好。

        3
  •  6
  •   kittylyst    13 年前

    只需在系统向真正的客户流量开放之前,通过系统运行一系列禁止操作的消息。通常是10千条信息。

    对于金融应用程序(例如fix),这通常是通过在它打开之前向市场发送订单(价格远离昨晚的收盘价,以防万一)来完成的。他们都会被拒绝,但这无关紧要。

    如果您使用的协议是自制的,那么下次升级它的库时,请添加对“预热”、“测试”或“sanitycheck”消息类型的显式支持。

    当然,这可能不会编译应用程序逻辑特定的路径,但在一个体面的消息传递应用程序中,处理网络流量的部分几乎肯定是堆栈的主要部分,因此这并不重要。

        4
  •  3
  •   Jesper    16 年前

    您使用的是客户机还是服务器JVM?尝试启动程序时使用:

    java -server com.mycompany.MyProgram
    

    在这种模式下运行Sun的JVM时,JIT会更早地将字节码编译为本机代码;因此,程序启动将花费更长的时间,但之后运行会更快。

    参考文献: Frequently Asked Questions About the Java HotSpot VM

    报价:

    客户机系统和服务器系统有什么区别?

    这两个系统是不同的二进制文件。它们本质上是两个不同的编译器(JIT)与同一运行时系统的接口。客户机系统最适合需要快速启动时间或较小占地面积的应用程序,服务器系统最适合总体性能最重要的应用程序。一般来说,客户机系统更适合于交互式应用程序,如guis。其他一些差异包括编译策略、堆默认值和内联策略。

        5
  •  3
  •   Andriy Plokhotnyuk    13 年前

    如果在当代硬件(每个CPU有2个或更多内核)和最新版本的JDK上以Hotspot的服务器模式运行,则可以使用以下选项加速预热:

    -server -XX:+TieredCompilation
    
        6
  •  2
  •   John Conde    13 年前

    我知道,这是老线索,但我在网上找到的:

    一个非常有趣的事情是选项xx:compileThreshold=1500对Sun Hotspot JVM的影响。服务器虚拟机的默认值为10000,客户机虚拟机的默认值为1500。但是,对于服务器虚拟机,将其设置为1500会使其比客户机虚拟机更快。实际设置为100会降低性能。并且使用选项xcomp(这意味着所有代码都是在使用之前编译的)可以提供更低的性能,这令人惊讶。

    现在你知道该怎么做了。

        7
  •  -4
  •   amy    16 年前

    似乎您的项目将受益于实时保证:

    见: Real Time Java