我试图获得一种可靠的方法来测量磁盘读取速度,但是没有将缓存移出等式。
在How to measure Disk Speed in Java for Benchmarking中,simgineer实用程序正是如此,但由于某种原因,我无法复制其行为,并且运行该实用程序也不会产生任何精确的(用于读取)。
从不同答案中的建议,将测试文件设置为比主存大小更大的东西似乎工作,但是我不能花费整整四分钟来为系统分配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();}
}
我有点希望获得一个基准测试,该基准测试将在几秒钟内完成(后续运行的缓存结果),只有第一次执行有点更慢。
我可以在技术上抓取文件系统并对已经在驱动器上的文件进行读取操作,但这有点像未定义的行为,防火墙对它也不满意。
还剩下其他选择吗? (平台相关的库不在桌面上)
答案 0 :(得分:0)
最终决定通过搜索本地工作文件夹来解决问题并加载这些问题,希望我们打包应用程序以获得规格速度。在我目前的测试案例中,答案很幸运,但是没有保证,所以我将这个方法作为备份计划保留。
这不是完美的解决方案,但它有点工作,使规格速度大约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;
}