2017-04-21 118 views
2

我试图获得一些可靠的测量磁盘读取速度的方法,但是无法从等式中删除缓存。Java基准测试磁盘速度

How to measure Disk Speed in Java for Benchmarking对simgineer实用程序的回答正是这一点,但由于某种原因,我无法复制其行为,并且运行该实用程序不会产生任何精确的(用于读取)。

从建议在不同的答案,测试文件设置的东西比主存储器容量更大的似乎工作,但我不能花整整4分钟,系统分配130GB的文件。 (不写在稀疏文件的文件结果任何东西,返回假倍)

足够的文件大小似乎

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();} 
} 

我有点希望得到一个基准,将完成withi n秒(缓存结果为以下运行)只有第一次执行有点较慢。

我可以在技术上抓取文件系统和板凳上的是已经在驱动器上的文件的读取,但闻起来像很多不确定的行为和防火墙都不满意,要么。

还剩下的其他选项? (依赖于平台的库是假表)

+0

纠正我,如果我错了,但你只能“缓存”,你知道是什么。如果读取文件,则必须从磁盘读取文件,因为文件内容未知。因此没有缓存效果(前提是文件未被加载到RAM中)。 – Turing85

+0

读取和写入的文件都会进入缓存。无论如何,我可以向你保证,从机械驱动器读取2GB/s的数据是有点可怕的。正如我所提到的,足够大的文件将导致与磁盘规格相对应的读取速度。 –

+0

你可以打开整个d:驱动器并读取java中的随机扇区吗?我们在C++中这样做,但不确定这在java中是否可行。 – rlb

回答

0

最终决定由淘本地工作文件夹中的文件来解决问题,并加载这些,希望我们打包足以与应用得到规范的速度。在我目前的测试案例中,答案是幸运的是,但没有任何保证,所以我将这个问题作为备份计划。

这是不完全完美的解决方案,但有些作品,越来越规格速度约2000测试文件。请记住,此测试不能以相同的结果重新运行,因为之前执行的所有测试文件现在都可能被缓存。

您可以随时拨打乍得奥斯汀的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; 
}