当前位置: 代码迷 >> java >> 优化器行为怪异:JVM坚持一种优化,无法适应
  详细解决方案

优化器行为怪异:JVM坚持一种优化,无法适应

热度:48   发布时间:2023-07-17 20:17:25.0

我的过程很漫长,有两个主要阶段。 第一阶段和第二阶段的执行路径略有不同。

我刚刚意识到,如果我用不同的名称创建相同方法的副本,并在每个阶段使用不同的名称,那么根据JMH( -server ,在java-7-openjdk-amd64 ),我可以得到25%以上的加速该方法在第二阶段进行调用(超过5次调用预热后,以5次调用衡量的方法调用数百万次)。

有没有办法告诉JVM忘记关于方法的先前优化并从头开始重新学习?

在以下示例代码中, run了基准测试方法, checkChar0stage2调用checkCharcheckChar0两个版本之间进行了比较。

final public void run(){
   sumStg1=0;
   for(int i=0; i< 10000; i++){
      String str = consumeString();
      for(int i= 0; i<K; i++){
         sumStg1 += checkChar(str.charAt(i), i)?1:0;
      }
   }

   sumStg2=0;
   for(int j=0; j< 10000000; j++){
      String str = consumeString();
      for(int i=K/2; i<str.length(); i++){
         sumStg2 += checkChar(str.charAt(i), i)?1:0;
      }
   }
}

final public boolean checkChar(char in, int i){
   if(i < K/2){
     ...
   } else if (i < K){
     ...
   } else {
     ...
   }
}

//identical method to checkChar
final public boolean checkChar0(char in, int i){
   if(i < K/2){
     ...
   } else if (i < K){
     ...
   } else {
     ...
   }
}

我想到两个想法:

A)通过调用该方法,并使用指向该方法的新方法句柄对其进行更新,然后调用应该触发调用方法的重新编译。

提供类似的功能。

我不知道的是,JVM是否可以在此处应用任何技巧,如果方法被自身替换,则跳过重新编译。

B)应用一个类文件重新 ,该本质上不会改变任何东西,除了可能将一些惰性字节码附加到方法主体或其他任何东西上。

请注意,我还没有尝试过任何方法,因此无法保证。


您也可能没有基准测试基准。 JMH并不是魔术棒,只需挥舞代码即可消除所有测量问题。

您说您的实际应用程序包含两个阶段,并且只有一个阶段过渡。

但是在JMH中,您总体上使用了10个迭代(每个迭代有N个调用),这意味着随着新迭代的开始,将进行10 * N个正向相位转换和10 * N个反向转换。 这最终将导致JIT放弃重新编译。

JMH旨在在您的应用程序依赖一次性行为的情况下测量稳态性能。

另一个想法:

  • 在新的类加载器中再次加载该类,并使用该版本而不是静态加载的版本。

  • -XX:CompileThreshold设置更大的值。

(这两种方法都有明显的/明显的缺点,但是如果性能对您而言如此重要……)

  相关解决方案