我的迷你基准:
import java.math.*;
import java.util.*;
import java.io.*;
public class c
{
static Random rnd = new Random();
public static String addDigits(String a, int n)
{
if(a==null) return null;
if(n<=0) return a;
for(int i=0; i<n; i++)
a+=rnd.nextInt(10);
return a;
}
public static void main(String[] args) throws IOException
{
int n = 10000; \\number of iterations
int k = 10; \\number of digits added at each iteration
BigInteger a;
BigInteger b;
String as = "";
String bs = "";
as += rnd.nextInt(9)+1;
bs += rnd.nextInt(9)+1;
a = new BigInteger(as);
b = new BigInteger(bs);
FileWriter fw = new FileWriter("c.txt");
long t1 = System.nanoTime();
a.multiply(b);
long t2 = System.nanoTime();
//fw.write("1,"+(t2-t1)+"\n");
if(k>0) {
as = addDigits(as, k-1);
bs = addDigits(as, k-1);
}
for(int i=0; i<n; i++)
{
a = new BigInteger(as);
b = new BigInteger(bs);
t1 = System.nanoTime();
a.multiply(b);
t2 = System.nanoTime();
fw.write(((i+1)*k)+","+(t2-t1)+"\n");
if(i < n-1)
{
as = addDigits(as, k);
bs = addDigits(as, k);
}
System.out.println((i+1)*k);
}
fw.close();
}
}
测量n位BigInteger的乘法时间
结果:
你可以很容易地看到趋势,但为什么有超过50000位的噪音? 这是因为垃圾收集器还是有其他东西会影响我的结果? 执行测试时,没有其他应用程序在运行。
测试结果只有奇数位。测试时间较短(n = 1000,k = 100)
奇数位(n = 10000,k = 10)
正如你所看到的,在65000到70000之间有一个巨大的噪音。我想知道为什么......
奇数位(n = 10000,k = 10),每1000次迭代System.gc()
结果噪音在50000-70000之间
答案 0 :(得分:9)
我也怀疑这是一个JVM预热效果。不是涉及类加载或JIT编译器的预热,而是堆的预热。
在整个基准测试周围放置一个(java)循环,并运行它多次。 (如果这给你的图表与以前相同......你会有证据这不是一个预热效果。目前你没有任何经验证据。)
另一种可能性是噪音是由您的基准测试与操作系统和/或机器上运行的其他内容的交互引起的。
nanoTime()
拨打大量电话,可能会引入噪音。最后,一定量的噪音是不可避免的,因为每个multiply
调用都会产生垃圾,垃圾收集器需要处理它。
最后,最后,如果你手动运行垃圾收集器(或增加堆大小)到&#34;平滑&#34;数据点,你实际在做的是隐瞒multiply
电话的费用之一。生成的图表看起来不错,但这是误导性的:
multiply
的真实成本实际上包括运行GC以处理呼叫产生的垃圾的摊销成本。要获得反映BigInteger
在现实生活中的行为方式的测量,您需要多次运行测试,计算平均时间并将曲线拟合到平均数据点。
请记住,游戏的真正目的是获得科学有效的结果......而不是平滑的曲线。
答案 1 :(得分:3)
如果你做一个微基准测试,你必须'#34;热身&#34; JVM首先让JIT优化代码,然后就可以测量性能。否则,您正在测量JIT完成的工作,并且可以在每次运行时更改结果。
&#34;噪音&#34;可能是因为超出了CPU的缓存并且性能开始下降。