java - `scale` 中的 `BigDecimal#divide()` 越高,速度越快?

标签 java performance bigdecimal

我提出了一个问题,最初是一个问答式的问题。

原问题:

scale 中的 BigDecimal#divide() 越高,对性能的影响有多大?

所以,我创建了这个 SSCCE:

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;

public class Test {

    public static void main(String args[]) {
        int[] scales = new int[] {1, 10, 50, 100, 500, 1000, 5000, 100000, 1000000};
        for(Integer scale : scales) {
            long start = System.nanoTime();
            BigDecimal.ONE.divide(BigDecimal.valueOf(7), scale, RoundingMode.HALF_UP);
            long end = System.nanoTime();
            long elapsed = end - start;
            String elapsed_str = String.format("%d mins, %d secs, %d millis, %d nanos", 
                TimeUnit.NANOSECONDS.toMinutes(elapsed),
                TimeUnit.NANOSECONDS.toSeconds(elapsed) - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(elapsed)),
                TimeUnit.NANOSECONDS.toMillis(elapsed) - TimeUnit.SECONDS.toMillis(TimeUnit.NANOSECONDS.toSeconds(elapsed)),
                elapsed - TimeUnit.MILLISECONDS.toNanos(TimeUnit.NANOSECONDS.toMillis(elapsed))
            );
            System.out.println("Time for scale = " + scale + ": " + elapsed_str);
        }
    }
}

输出如下:

Time for scale = 1: 0 mins, 0 secs, 2 millis, 883903 nanos
Time for scale = 10: 0 mins, 0 secs, 0 millis, 13995 nanos
Time for scale = 50: 0 mins, 0 secs, 1 millis, 138727 nanos
Time for scale = 100: 0 mins, 0 secs, 0 millis, 645636 nanos
Time for scale = 500: 0 mins, 0 secs, 1 millis, 250220 nanos
Time for scale = 1000: 0 mins, 0 secs, 4 millis, 38957 nanos
Time for scale = 5000: 0 mins, 0 secs, 15 millis, 66549 nanos
Time for scale = 100000: 0 mins, 0 secs, 500 millis, 873987 nanos
Time for scale = 1000000: 0 mins, 50 secs, 183 millis, 686684 nanos

随着数量级的增加,性能受到指数级影响。但让我摸不着头脑的是这些行:

Time for scale = 1: 0 mins, 0 secs, 2 millis, 883903 nanos
Time for scale = 10: 0 mins, 0 secs, 0 millis, 13995 nanos
Time for scale = 50: 0 mins, 0 secs, 1 millis, 138727 nanos
Time for scale = 100: 0 mins, 0 secs, 0 millis, 645636 nanos
Time for scale = 500: 0 mins, 0 secs, 1 millis, 250220 nano

看来 10 的规模对于 BigDecimal#divide() 来说是最佳的? 100 的规模比 50 更快?我认为这可能只是一个异常,所以我再次运行了它(这次,省略了最高的两个刻度,因为我不想等待 50 秒:)),这就是结果:

Time for scale = 1: 0 mins, 0 secs, 3 millis, 440903 nanos
Time for scale = 10: 0 mins, 0 secs, 0 millis, 10263 nanos
Time for scale = 50: 0 mins, 0 secs, 0 millis, 833169 nanos
Time for scale = 100: 0 mins, 0 secs, 0 millis, 487492 nanos
Time for scale = 500: 0 mins, 0 secs, 0 millis, 802846 nanos
Time for scale = 1000: 0 mins, 0 secs, 2 millis, 475715 nanos
Time for scale = 5000: 0 mins, 0 secs, 16 millis, 646117 nanos

同样, 101 快得多,并且 100 又比 50 快。

我一次又一次地尝试,100 总是比 50 更快。并且 1 的规模总是比小于 1000 的所有内容慢。

谁能解释一下吗?

最佳答案

Java 代码是动态优化的,但是第一次运行它时,必须加载它。为了避免在运行时重新编译代码而导致困惑的结果,我建议

  • 首先进行最长的运行,而不是最后。
  • 运行测试至少 2 秒。
  • 忽略至少 3 到 5 次运行中的第一次运行(在本例中只有一次)

我会保持比例简单,以便您可以比较所有结果。在你的例子中,我会每一项至少执行 1000 次,并以微秒为单位打印平均值。

关于java - `scale` 中的 `BigDecimal#divide()` 越高,速度越快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20671058/

相关文章:

mysql - 为什么这个查询总是很慢

PHP - 以某种方式散列对象具有相同字段值的不同对象具有相同的散列

java - 估计 BigDecimal 计算时间

java - Glassfish:一个或多个Web片段以冲突的方式定义同一个Servlet,并且该Servlet未在web.xml中定义

java - 从 Java 连接到 SockJS?

c - 哪个更有效率?重复分配或重复检查

java - "new BigDecimal(13.3D)"结果不精确 "13.3000000000000007105.."?

java - 等待多个 SwingWorker

java - 如何在 Kotlin 中创建一个在 Java 中也是不可变列表的不可变列表?

java - 删除前导 0 直至小数点