2

我编写了简单的基准测试来测试乘法双打与 BigDecimal 的性能。我的方法正确吗?我使用随机值是因为编译器多次优化了乘法常量(例如Math.PI * Math.E)。
但是:
- 我不知道在测试中生成随机数是否会破坏结果。
- 在测试中创建新BigDecimal对象也是如此。

我只想测试乘法的性能(不是构造函数使用的时间)。

如何做呢?

import java.math.*;
import java.util.*;

public class DoubleVsBigDecimal
{
    public static void main(String[] args)
    {
        Random rnd = new Random();
        long t1, t2, t3;
        double t;

        t1 = System.nanoTime();

        for(int i=0; i<1000000; i++)
        {
            double d1 = rnd.nextDouble();
            double d2 = rnd.nextDouble();
            t = d1 * d2;
        }

        t2 = System.nanoTime();

        for(int i=0; i<1000000; i++)
        {
            BigDecimal bd1 = BigDecimal.valueOf(rnd.nextDouble());
            BigDecimal bd2 = BigDecimal.valueOf(rnd.nextDouble());
            bd1.multiply(bd2);
        }

        t3 = System.nanoTime();

        System.out.println(String.format("%f",(t2-t1)/1e9));
        System.out.println(String.format("%f",(t3-t2)/1e9));
        System.out.println(String.format("%f",(double)(t3-t2)/(double)(t2-t1)));
    }
}
4

4 回答 4

3

您不仅在为乘法运算计时,还在为其他事情计时。

您需要执行以下操作:

    long time = 0; 
    for(int i=0; i<1000000; i++) {
        double d1 = rnd.nextDouble();
        double d2 = rnd.nextDouble();
        long start = System.nanoTime();
        t = d1 * d2;
        long end = System.nanoTime();
        time += (end-start)
    }
    long meantime = time / 1000000;

然后可能也会计算标准误差。此外,您可能需要在开始之前先对 jvm 进行一些计算,否则您将在开始时获得一些较高的值。

于 2012-05-22T19:15:32.383 回答
3

Java 中的基准测试真的很奇怪。 例如,JVM 实际上不会完全优化一段代码,直到它已经运行了很多次——但是在优化之后进行测量会更公平,因为任何生产系统都会多次调用这个方法。

Java 基准测试还有很多其他问题。避免它们的最简单方法可能是使用由专家构建的 Java 基准测试工具,例如Caliper

于 2012-05-22T19:21:52.250 回答
1

您可以预先生成两个包含 1000 个双精度数/BigDecimals 的集合,并在 2 个嵌套循环中将每个与每个相乘:

public static void main(String[] args)
{
    Random rnd = new Random();
    List <Double> dl = new ArrayList <Double> ();
    List <BigDecimal> bdl = new ArrayList <BigDecimal> ();

    for(int i=0; i<1000; i++)
    {
        double d = rnd.nextDouble();
        dl.add (d);
        bdl.add (new BigDecimal (d));
    }

    long t1 = System.nanoTime();
    double t;
    for (double d1 : dl)
            for (double d2 : dl)
                t = d1 * d2;

    long t2 = System.nanoTime();

    for (BigDecimal b1 : bdl)
        for (BigDecimal b2 : bdl)
                b1.multiply (b2);

    long t3 = System.nanoTime();

    System.out.println (String.format ("%f", (t2 - t1) / 1e9));
    System.out.println (String.format ("%f", (t3 - t2) / 1e9));
    System.out.println (String.format ("%f", (double) (t3 - t2) / (double) (t2 - t1)));
} 

重复时,第一个代码会产生像这样的非常稳定的值:

0,186755
10,970243
58,741445

我的代码有不同的值,但也很稳定:

0,077177
1,112490
14,414710

关系的差异是1:4,这几乎是。没有关系 BigDecimal:double 那么多,但很好 ---

(i386-32、客户端模式、JRE-1.6、linux、oracle、2Ghz Centrino 单核)。

于 2012-05-22T19:43:45.180 回答
1

我强烈推荐这篇文章作为基准测试的介绍:

http://www.ibm.com/developerworks/java/library/j-benchmark1/index.html

于 2012-05-22T20:08:27.963 回答