Java BigDecimal奇怪的性能行为

Water Guo

今天,我遇到了BigDecimal的一种奇怪的性能行为。简而言之,以下两段试图做同一件事的代码之间存在显着差异

int hash = foo();
BigDecimal number = new BigDecimal(hash);

BigDecimal number = new BigDecimal(foo());

为了证明这一点,我在下面的课程中展示了差异。我的Java是1.7.0_75-b13,64位,mac。在我的环境中,第一个循环耗时2s,第二个循环耗时5s。

import java.math.BigDecimal;

public class Crazy {

public static void main(String[] args) {
    new Crazy().run();
}

void run() {
    // init

    long count = 1000000000l;

    // start test 1

    long start = System.currentTimeMillis();

    long sum = 0;
    for (long i=0; i<count; i++) {
        sum = add(sum);
    }

    long end = System.currentTimeMillis();
    System.out.println(end - start);

    // start test 2

    long start2 = end;
    sum = 0;
    for (long i=0; i<count; i++) {
        sum = add1(sum);
    }

    long end2 = System.currentTimeMillis();
    System.out.println(end2 - start2);
}

long add(long sum) {
    int hash = hashCode();
    BigDecimal number = new BigDecimal(hash);
    sum += number.longValue();
    return sum;
}

long add1(long sum) {
    BigDecimal number = new BigDecimal(hashCode());
    sum += number.longValue();
    return sum;
}
}

javap输出

long add(long);
Code:
   0: aload_0       
   1: invokevirtual #56                 // Method java/lang/Object.hashCode:()I
   4: istore_3      
   5: new           #60                 // class java/math/BigDecimal
   8: dup           
   9: iload_3       
  10: invokespecial #62                 // Method java/math/BigDecimal."<init>":(I)V
  13: astore        4
  15: lload_1       
  16: aload         4
  18: invokevirtual #65                 // Method java/math/BigDecimal.longValue:()J
  21: ladd          
  22: lstore_1      
  23: lload_1       
  24: lreturn       

long add1(long);
Code:
   0: new           #60                 // class java/math/BigDecimal
   3: dup           
   4: aload_0       
   5: invokevirtual #56                 // Method java/lang/Object.hashCode:()I
   8: invokespecial #62                 // Method java/math/BigDecimal."<init>":(I)V
  11: astore_3      
  12: lload_1       
  13: aload_3       
  14: invokevirtual #65                 // Method java/math/BigDecimal.longValue:()J
  17: ladd          
  18: lstore_1      
  19: lload_1       
  20: lreturn      
菲利普·马歇尔

我无法重现。考虑以下微基准测试:

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class BigDecimalBenchmark {

  static int i = 1024;

  @Benchmark
  public BigDecimal constructor() {
    return new BigDecimal(foo());
  }

  @Benchmark
  public BigDecimal localVariable() {
    int hash = foo();
    return new BigDecimal(hash);
  }

  private static int foo() {
    return i;
  }

}

给出以下输出:

Benchmark                             Mode  Samples       Score      Error   Units
BigDecimalBenchmark.constructor      thrpt      100  180368.227 ± 4280.269  ops/ms
BigDecimalBenchmark.localVariable    thrpt      100  173519.036 ±  868.547  ops/ms

更新

编辑基准以使foo()不可内联。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章