使用Java进行硬盘驱动器基准测试,获得不合理的快速结果

时间:2016-06-13 09:50:48

标签: java benchmarking fileinputstream fileoutputstream hard-drive

我写了一个代码来对硬盘进行基准测试。这很简单:使用BufferedOutputStream将大块字节(2500 * 10M)写入磁盘,然后使用BufferedInputStream读取它。我每次写入2500字节,持续10M次,以模拟我写的另一个程序中的条件。还有另一个全局变量,“无意义”,用读取字节计算 - 它绝对没有意义,并且仅用于强制执行实际读取和使用字节(以避免不读取字节的情况)由于一些优化)。

代码运行4次并输出结果。

这是:

import java.io.*;

public class DriveTest
{
    public static long meaningless = 0;

    public static String path = "C:\\test";

    public static int chunkSize = 2500;

    public static int iterations = 10000000;

    public static void main(String[] args)
    {
        try
        {
            for(int i = 0; i < 4; i++)
            {
                System.out.println("Test " + (i + 1) + ":");
                System.out.println("==================================");

                write();
                read();

                new File(path).delete();

                System.out.println("==================================");
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    private static void write() throws Exception
    {
        BufferedOutputStream bos = new BufferedOutputStream(
                                   new FileOutputStream(new File(path)));

        long t1 = System.nanoTime();

        for(int i = 0; i < iterations; i++)
        {
            byte[] data = new byte[chunkSize];

            for(int j = 0; j < data.length; j++)
            {
                data[j] = (byte)(j % 127);
            }

            bos.write(data);
        }

        bos.close();

        long t2 = System.nanoTime();

        double seconds = ((double)(t2 - t1) / 1000000000.0);

        System.out.println("Writing took " + (t2 - t1) + 
                           " ns (" + seconds + " seconds).");

        System.out.println("Write rate " + (((double)chunkSize * 
                           iterations / seconds) / 
                           (1024.0 * 1024.0)) + " MB/s.");
    }

    private static void read() throws Exception
    {
        BufferedInputStream bis = new BufferedInputStream(
                                  new FileInputStream(new File(path)));

        long t1 = System.nanoTime();

        byte[] data;

        for(int i = 0; i < iterations; i++)
        {
            data = new byte[chunkSize];

            bis.read(data);

            meaningless += data[i % chunkSize];
        }

        bis.close();

        long t2 = System.nanoTime();

        System.out.println("meaningless is: " + meaningless + ".");

        double seconds = ((double)(t2 - t1) / 1000000000.0);

        System.out.println("Reading Took " + (t2 - t1) + 
                           " ns, which is " + 
                           seconds + " seconds.");

        System.out.println("Read rate " + (((double)chunkSize * 
                           iterations / seconds) / 
                           (1024.0 * 1024.0)) + " MB/s.");
    }
}

这里的问题有两个:

  1. 当迭代次数= 10M(写入~23GB到磁盘)时,常规的7200 RPM驱动器会提供非常快速的结果,高于规格:
  2. _

    Test 1:
    Writing took 148738975163 ns (148.738975163 seconds).
    Write rate 160.29327810029918 MB/s.
    meaningless is: 1246080000.
    Reading Took 139143051529 ns, which is 139.143051529 seconds.
    Read rate 171.34781541848795 MB/s.
    
    Test 2:
    Writing took 146591885655 ns (146.591885655 seconds).
    Write rate 162.64104799270686 MB/s.
    meaningless is: 1869120000.
    Reading Took 139845492688 ns, which is 139.845492688 seconds.
    Read rate 170.48713871206587 MB/s.
    
    Test 3:
    Writing took 152049678671 ns (152.049678671 seconds).
    Write rate 156.8030798785472 MB/s.
    meaningless is: 2492160000.
    Reading Took 140152776858 ns, which is 140.152776858 seconds.
    Read rate 170.11334662539255 MB/s.
    
    Test 4:
    Writing took 151363950081 ns (151.363950081 seconds).
    Write rate 157.51344951950355 MB/s.
    meaningless is: 3115200000.
    Reading Took 139176911081 ns, which is 139.176911081 seconds.
    Read rate 171.30612919179143 MB/s.
    

    这看起来很奇怪 - 磁盘真的能达到这样的速度吗?我严重怀疑,鉴于经过测试的规范(甚至在java输出/输入流中,根据我的新手意见 - 不应该是最佳的!)更低:http://hdd.userbenchmark.com/Toshiba-DT01ACA200-2TB/Rating/2736

    1. 当迭代次数设置为1M(1000000)时,数字会变得非常疯狂:
    2. _

      Test 1:
      Writing took 6918084976 ns (6.918084976 seconds).
      Write rate 344.6308912490619 MB/s.
      meaningless is: 62304000.
      Reading Took 2060226375 ns, which is 2.060226375 seconds.
      Read rate 1157.244572706543 MB/s.
      
      Test 2:
      Writing took 6970893036 ns (6.970893036 seconds).
      Write rate 342.0201369756931 MB/s.
      meaningless is: 124608000.
      Reading Took 2013661185 ns, which is 2.013661185 seconds.
      Read rate 1184.0054368508995 MB/s.
      
      Test 3:
      Writing took 7140592101 ns (7.140592101 seconds).
      Write rate 333.89188981705496 MB/s.
      meaningless is: 186912000.
      Reading Took 2011346987 ns, which is 2.011346987 seconds.
      Read rate 1185.367719456367 MB/s.
      
      Test 4:
      Writing took 7140064035 ns (7.140064035 seconds).
      Write rate 333.91658384694375 MB/s.
      meaningless is: 249216000.
      Reading Took 2041787713 ns, which is 2.041787713 seconds.
      Read rate 1167.6952387535623 MB/s.
      

      这是什么样的缓存巫术? (什么样的缓存可以导致更快?):)它怎么能被撤消?我有2.3GB的读写文件!如果确实存在问题,这是一些巨大的缓存。

      由于

1 个答案:

答案 0 :(得分:3)

您的测试可能只是读取和写入操作系统页面缓存。小数据大小将完全适合。较大的一个不会被操作系统异步刷新。您应该尝试使用OpenOptions.DSYNC和SYNC选项。