2011-07-06 47 views
0

我必須編寫一個用Java進行外部排序的算法,只使用JVM RAM(基本上,我不能映射文件)。因此,我想要做的第一部分是從塊中讀取文件中的數據。我發現this tutorial外部排序優化

問題是,教程是關於閱讀byte s,我必須閱讀int s。我不確定IntBuffer是如何實現的,但我認爲它是一個字節緩衝區的包裝。鑑於這個事實,我說我能做的最快的事情是使用教程中的「FileChannel with ByteBuffer和byte array」方法(下面的代碼),然後創建一個單獨的數組,並用「手動」方式創建單獨的數組,使用位操作從字節獲取?

FileInputStream f = new FileInputStream(name); 
FileChannel ch = f.getChannel(); 
ByteBuffer bb = ByteBuffer.allocateDirect(BIGSIZE); 
byte[] barray = new byte[SIZE]; 
long checkSum = 0L; 
int nRead, nGet; 
while ((nRead=ch.read(bb)) != -1) 
{ 
    if (nRead == 0) 
     continue; 
    bb.position(0); 
    bb.limit(nRead); 
    while(bb.hasRemaining()) 
    { 
     nGet = Math.min(bb.remaining(), SIZE); 
     bb.get(barray, 0, nGet); 
     for (int i=0; i<nGet; i++) 
      checkSum += barray[i]; 
    } 
    bb.clear(); 
} 

另外,我有一個小的附加的問題:我想讀和排序在並行(I/O浪費了大量的時間),應該使用一種完全不同的方法,或者在一個正在使用此方法線程和排序在其他線程的好方法?我真的想爭取每一秒的表現。

+6

我認爲你應該寫一些首先起作用的東西,然後*爭取達到納秒的性能。當你無法測量時,你將如何預測速度更快? –

+1

什麼是「JVM RAM」? –

回答

1
new DataInputStream(new BufferedInputStream(new FileInputStream(file))); 

然後使用readInt()。這與使用FileChannel完成映射文件的任何操作一樣快,而且它們只比正常I/O快大約20%。

直接字節緩衝區不會幫助你在這裏。當你不想自己查看或修改數據時,它們是最有用的,你只是在通道之間進行復制。它保存了跨越JNI/Java邊界兩次的數據,只是將其保存在JNI層中。不適用於這種情況。

+0

嗨,謝謝你的迴應! 那麼,異步閱讀呢?它是如何實現的?它嘗試提前閱讀,還是應該初始化單獨的線程以提前閱讀?什麼是默認緩衝區大小? 感謝您的幫助! – nivwusquorum

+1

1.7之前的Java中沒有異步讀取。你只需要獲得磁盤控制器和操作系統的任何東西,這實際上非常廣泛:緩存,預讀,各種東西。 BufferedInputStream的默認緩衝區大小是8192(雖然沒有指定),這應該是足夠的:如果不是,請嘗試使用它,大的因素,例如。嘗試64k。 – EJP

1

如果你想爭取以往的納秒性能購買更快的磁盤,例如使用SSD或RAID N或兩者兼而有之。 SSD驅動器可以將數據傳輸速度比移動磁盤快10倍。這將比你在Java中可以做的任何事情都有更多的不同。