Java 为什么JVM需要预热?

Java 为什么JVM需要预热?,java,garbage-collection,jvm,low-latency,hft,Java,Garbage Collection,Jvm,Low Latency,Hft,我知道在Java虚拟机(JVM)中,可能需要预热,因为Java使用延迟加载过程加载类,因此您希望确保在启动主事务之前初始化对象。我是C++开发人员,没有处理类似的要求。 但是,我无法理解的部分如下: 您应该预热代码的哪些部分 即使我预热了代码的某些部分,它还能保持多长时间(假设这个术语只表示类对象在内存中保留多长时间) 如果我每次收到事件时都需要创建对象,那么它有什么帮助 例如,考虑一个应用程序,该应用程序预期通过套接字接收消息,事务可以是New Order、Modify Order和Cance

我知道在Java虚拟机(JVM)中,可能需要预热,因为Java使用延迟加载过程加载类,因此您希望确保在启动主事务之前初始化对象。我是C++开发人员,没有处理类似的要求。 但是,我无法理解的部分如下:

  • 您应该预热代码的哪些部分
  • 即使我预热了代码的某些部分,它还能保持多长时间(假设这个术语只表示类对象在内存中保留多长时间)
  • 如果我每次收到事件时都需要创建对象,那么它有什么帮助
  • 例如,考虑一个应用程序,该应用程序预期通过套接字接收消息,事务可以是New Order、Modify Order和Cancel Order或transaction confirmed


    请注意,该应用程序是关于高频交易(HFT)的,因此性能非常重要。

    它是关于
    JIT
    编译器的,该编译器在
    JVM
    上用于在运行时优化字节码(因为
    javac
    由于字节码的平台无关性,无法使用高级或激进的优化技术)

  • 您可以对处理消息的代码进行预热。实际上,在大多数情况下,您不需要通过特殊的预热周期来对其进行预热:只需让应用程序启动并处理一些最初的消息-
    JVM
    将尽力分析代码执行并进行优化:)使用假样品进行手动预热可能会产生更糟糕的结果

  • 代码将在一段时间后进行优化,直到程序流中的某个事件降低代码状态(在它
    JIT
    之后,编译器将再次尝试优化代码-此过程永远不会结束)

  • 短生命对象也是需要优化的对象,但一般来说,它会帮助您的消息处理终身代码更高效

  • 很少需要热身。例如,在进行性能测试时,确保JIT预热时间不会扭曲结果是相关的

    在正常的生产代码中,您很少看到用于预热的代码。JIT将在正常处理过程中预热,因此仅为此引入额外代码没有什么好处。在最坏的情况下,您可能会引入bug,花费额外的开发时间,甚至损害性能


    除非你确定你需要热身,否则别担心。您描述的示例应用程序当然不需要它。

    Warming指的是让一段代码运行足够的时间,以便JVM停止解释并编译为本机代码(至少是第一次)。一般来说,这是你不想做的事情。原因是JVM收集有关其在代码生成过程中使用的问题代码的统计信息(类似于概要文件引导的优化)。因此,如果有问题的代码块被伪数据“加热”,而伪数据的属性与真实数据不同,那么很可能会影响性能

    编辑:由于JVM不能执行整个程序的静态分析(它不知道应用程序将加载什么代码),因此它可以根据收集到的统计信息猜测类型。作为一个例子,当调用一个虚函数(在C++中)在一个精确的调用位置,它决定所有类型都有相同的实现,那么调用被提升为直接调用(甚至内联)。如果后来证明该假设是错误的,那么旧代码必须“未编译”才能正常运行。AFAIK HotSpot将呼叫站点分类为单态(单个实现)、双态(正好两个..转换为if(imp1类型){imp1}else{imp2})和完全多态..虚拟分派

    还有另一种情况是,当您进行分层编译时,会发生重新编译。第一层将花费更少的时间尝试生成好的代码,如果该方法“足够热”,则会使用更昂贵的编译时代码生成器

    您应该预热代码的哪些部分

    一般来说,这个问题没有答案。这完全取决于您的应用程序

    即使我对代码的某些部分进行了预热,它还能保温多久 (假设该术语仅表示类对象保留的时间 在内存中)

    只要程序有对对象的引用,对象就会一直保留在内存中,没有任何特殊的弱引用使用或类似的东西。了解您的程序何时“有引用”某些内容可能比您乍一看所想的要模糊一些,但它是Java内存管理的基础,值得付出努力

    如果我有每次都需要创建的对象,它有什么帮助 我收到一个事件

    这完全取决于应用程序。一般来说没有答案

    我鼓励您学习和使用Java,以了解类加载、内存管理和性能监控等方面的内容。实例化一个对象需要一些时间,一般来说,加载一个类需要更多的时间(当然,这通常要少得多)。通常,一旦类被加载,它就会在程序的整个生命周期中一直保存在内存中——这是您应该理解的事情,而不仅仅是得到答案

    如果你还不知道,还有一些技巧需要学习。一些程序使用对象的“池”,在实际需要它们之前进行实例化,然后在需要时进行处理。这允许程序的时间关键部分避免在时间关键期间花费实例化时间。池维护对象的集合(10?100?1000?10000?),并在需要时实例化更多对象,等等。但是管理池是一项重要的编程工作,