2017-04-21 136 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; 
}