Java 大整数乘法时间

Java 大整数乘法时间,java,benchmarking,biginteger,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;

我的迷你基准:

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();
    }
}
import java.math.*;
导入java.util.*;
导入java.io.*;
公共c类
{
静态随机rnd=新随机();
公共静态字符串addDigits(字符串a,int n)
{
如果(a==null)返回null;

如果(n如果你做了一个微基准测试,你必须先“预热”JVM,让JIT优化代码,然后你才能测量性能。否则你就是在测量JIT完成的工作,这会改变每次运行的结果


出现“噪音”可能是因为CPU的缓存被超过,性能开始下降。

我还怀疑这是JVM预热效应。不是涉及类加载或JIT编译器的预热,而是堆的预热

围绕整个基准测试进行一个(java)循环,并运行多次。(如果这给了您与以前相同的图表…您将有证据证明这不是预热效应。目前您没有任何这样或那样的经验证据。)


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

  • 您正在将计时数据写入无缓冲流。这意味着大量的系统调用和(可能)大量细粒度磁盘写入
  • 您正在大量调用
    nanoTime()
    ,这可能会引入噪音
  • 如果您的机器上正在运行其他东西(例如,您正在浏览网页),这将使您的基准测试慢一点,并引入噪音
  • 如果您的机器上运行的内存太多,可能会存在物理内存方面的竞争

最后,一定量的噪声是不可避免的,因为每个
乘法
调用都会生成垃圾,垃圾收集器将需要工作来处理它


最后,如果您手动运行垃圾收集器(或增加堆大小)以“平滑”数据点,那么实际上您所做的是隐藏
乘法
调用的成本之一。生成的图看起来不错,但有误导性:

  • 噪音反映了现实生活中会发生什么
  • multiply
    的真正成本实际上包括运行GC处理调用生成的垃圾的摊销成本
要获得反映实际生活中
biginger
行为方式的测量值,您需要运行大量测试,计算平均时间,并将曲线拟合到平均数据点


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

你所展示的信息无法让你知道。为什么不试试'System.gc()`每500-1000次迭代一次,看看这是否会使它变得平滑。Sry用于脱离主题,但是,您使用的是什么程序?@ulu5您的链接与源代码一致,表示JDK不会更改算法。是gc,“减慢”的效果可能是jvm“预热”的结果。Call System.gc()不时在计时块之外进行确认。@hvgotcodes@esej来自“调用gc方法”的文档,表明Java虚拟机花费精力回收未使用的对象[…]”。换句话说,
System.gc()
只是对JVM的一个提示,无法知道GC是否、何时或如何实际执行。好的,但JVM未预热的情况是在模拟的一开始。稍后,我们可以假设预热状态。但噪声是在模拟结束时,而不是开始时