BigInteger中的乘法时间

Jan*_*jan 23 java benchmarking biginteger

我的迷你基准:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

它测量n位BigInteger的乘法时间

结果: 在此输入图像描述

你可以很容易地看到趋势,但为什么有超过50000位的噪音?这是因为垃圾收集器还是有其他东西会影响我的结果?执行测试时,没有其他应用程序在运行.

测试结果只有奇数位.测试时间较短(n = 1000,k = 100)

在此输入图像描述

奇数位(n = 10000,k = 10) 在此输入图像描述

正如你所看到的,在65000到70000之间有一个巨大的噪音.我想知道为什么......

奇数位(n = 10000,k = 10),System.gc()每1000次迭代 在此输入图像描述 结果噪音在50000-70000之间

Ste*_*n C 9

我也怀疑这是一个JVM预热效果.不是涉及类加载或JIT编译器的预热,而是堆的预热.

在整个基准测试中放置一个(java)循环,并运行它多次.(如果这给你的图形与以前相同......你会得到证据证明这不是一种预热效果.目前你没有任何经验证据.)


另一种可能性是噪音是由您的基准测试与操作系统和/或机器上运行的其他东西的交互引起的.

  • 您正在将计时数据写入无缓冲的流.这意味着很多系统调用,以及(可能)许多细粒度的光盘写入.
  • 你正在拨打很多电话nanoTime(),这可能会引入噪音.
  • 如果您的机器上正在运行其他东西(例如,您正在浏览网页),那么会降低您的基准测试速度并引入噪音.
  • 可能存在物理内存的竞争......如果你的机器上有太多的内存,那就是内存量.

最后,噪音一定量是必然的,因为每的multiply电话产生垃圾,垃圾收集器将需要合作来对付它.


最后,如果您手动运行垃圾收集器(或增加堆大小)以"平滑"数据点,那么您实际所做的是隐藏其中一个multiply调用成本.生成的图表看起来不错,但它有误导性:

  • 噪音反映了现实生活中会发生的事情.
  • 的真实成本multiply实际上包括运行GC来处理由呼叫产生的垃圾的摊余成本.

要获得反映BigInteger现实生活方式的测量结果,您需要多次运行测试,计算平均时间并将曲线拟合到平均数据点.

请记住,游戏的真正目的是获得科学有效的结果......而不是平滑的曲线.