Java 基准磁盘速度

Java benchmark disk speed

我正在尝试获得一些可靠的方法来测量磁盘读取速度,但无法从等式中删除缓存。

How to measure Disk Speed in Java for Benchmarking 中,simgineer 实用程序正是为此做出了回答,但出于某种原因,我未能复制其行为,并且 运行 该实用程序也没有产生任何精确信息(阅读).

根据不同答案的建议,将测试文件设置为大于主内存大小的东西似乎可行,但我不能花整整四分钟让系统分配 130GB 文件。 (不在文件中写入任何内容会导致文件稀疏和 returns 虚假时间)

足够的文件大小似乎介于

之间
Runtime.getRuntime().maxMemory() 

Runtime.getRuntime().maxMemory()*2

我目前方案的源码:

File file = new File(false ? "D:/work/bench.dat" : "./work/bench.dat");
RandomAccessFile wFile = null, rFile = null;
try {
    System.out.println("Allocating test file ...");
    int blockSize = 1024*1024;
    long size = false ? 10L*1024L*(long)blockSize : Runtime.getRuntime().maxMemory()*2;
    byte[] block = new byte[blockSize];
    for(int i = 0; i<blockSize; i++) {
        if(i % 2 == 0) block[i] = (byte) (i & 0xFF);
    }

    System.out.println("Writing ...");
    wFile = new RandomAccessFile(file,"rw");
    wFile.setLength(size);
    for(long i = 0; i<size-blockSize; i+= blockSize) {
        wFile.write(block);
    }
    wFile.close();

    System.out.println("Running read test ...");
    long t0 = System.nanoTime();

    rFile = new RandomAccessFile(file,"r");
    int blockCount = (int)(size/blockSize)-1;
    Random rnd = new Random();
    for(int i = 0; i<testCount; i++) {
        rFile.seek((long)rnd.nextInt(blockCount)*(long)blockSize);
        rFile.readFully(block, 0, blockSize);
    }
    rFile.close();

    long t1 = System.nanoTime();

    double readB = ((double)testCount*(double)blockSize);
    double timeNs = (double)(t1-t0);

    return (readB/(1024*1024))/(timeNs/(1000*1000*1000));
} catch (Exception e) {
    Logger.logError("Failed to benchmark drive speed!", e);
    return 0;
} finally {
    if(wFile != null) {try {wFile.close();} catch (IOException e) {}}
    if(rFile != null) {try {rFile.close();} catch (IOException e) {}}
    if(file.exists()) {file.delete();}
}

我有点希望得到一个可以在几秒钟内完成的基准测试(缓存后续运行的结果),只有第一次执行 稍微 慢一些。

我可以在技术上抓取文件系统并对驱动器上已有的文件进行基准读取,但这闻起来像很多未定义的行为,防火墙对此也不满意。

还有其他选择吗? (平台相关库已关闭 table)

最后决定通过在本地工作文件夹中搜索文件并加载这些文件来解决问题,希望我们与应用程序打包足够多以获得规格速度。在我当前的测试用例中,幸运的是答案是肯定的,但没有任何保证,所以我将这种方法作为备用计划保留下来。

这不是完全完美的解决方案,但它有点管用,在大约 2000 个测试文件时获得规格速度。请记住,此测试无法重新运行 得到相同的结果,因为之前执行的所有测试文件现在可能都已缓存。

您始终可以调用 Chad Austin 的 flushmem ( https://chadaustin.me/flushmem/ ),但这需要与原始方法一样多的时间来执行,所以我建议简单地缓存第一个 运行 并希望一切顺利。

使用代码:

final int MIN_FILE_SIZE = 1024*10;
final int MAX_READ = 1024*1024*50;
final int FILE_COUNT_FRACTION = 4;

// Scour the location of the runtime for any usable files.
ArrayList<File> found = new ArrayList<>();
ArrayList<File> queue = new ArrayList<>();
queue.add(new File("./"));
while(!queue.isEmpty() && found.size() < testCount) {
    File tested = queue.remove(queue.size()-1);
    if(tested.isDirectory()) {
        queue.addAll(Arrays.asList(tested.listFiles()));
    } else if(tested.length()>MIN_FILE_SIZE){
        found.add(tested);
    }
}

// If amount of found files is not sufficient, perform test with new file.
if(found.size() < testCount/FILE_COUNT_FRACTION) {
    Logger.logInfo("Disk to CPU transfer benchmark failed to find "
            + "sufficient amount of files to read, slow version "
            + "will be performed!", found.size());
    return benchTransferSlowDC(testCount);
}

System.out.println(found.size());

byte[] block = new byte[MAX_READ];
Collections.shuffle(found);
RandomAccessFile raf = null;
long readB = 0;
try {
    long t0 = System.nanoTime();

    for(int i = 0; i<Math.min(found.size(), testCount); i++) {
        File file = found.get(i);
        int size = (int) Math.min(file.length(), MAX_READ);
        raf = new RandomAccessFile(file,"r");
        raf.read(block, 0, size);
        raf.close();
        readB += size;
    }
    long t1 = System.nanoTime();

    return ((double)readB/(1024*1024))/((double)(t1-t0)/(1000*1000*1000));
    //return (double)(t1-t0) / (double)readB;
} catch (Exception e) {
    Logger.logError("Failed to benchmark drive speed!", e);
    if(raf != null) try {raf.close();} catch(Exception ex) {}
    return 0;
}