我写了一个简单的基准测试,测试多打双打与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)));
}
}
答案 0 :(得分: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,否则您将在开始时获得一些高值。
答案 1 :(得分:3)
Java中的基准测试非常奇怪。例如,JVM实际上并不会完全优化一段代码,直到它已经运行多次 - 但是之后进行测量更加公平这种优化,因为任何生产系统都会多次调用这种方法。
Java基准测试还有很多其他问题。可能最简单的避免它们的方法是使用由专家构建的Java基准测试工具,例如: Caliper
答案 2 :(得分: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单核)。
答案 3 :(得分:1)
我强烈推荐这篇文章作为基准测试的介绍:
http://www.ibm.com/developerworks/java/library/j-benchmark1/index.html