簡體   English   中英

Java:對巨大磁盤文件進行隨機讀取的最快方法

[英]Java: fastest way to do random reads on huge disk file(s)

我有一個中等大小的數據集,大約800 MB左右,這基本上是一個很大的預計算表,我需要將一些計算加速幾個數量級(創建該文件需要幾個mutlicores計算機天來使用優化生成和多線程算法......我真的需要那個文件)。

現在已經計算了一次,那么800MB的數據是只讀的。

我無法忍受它在記憶中。

截至目前,它是一個巨大的800MB文件,但如果可以提供幫助,拆分成較小的文件不是問題。

我需要在該文件中讀取大約32位數據的大量時間。 我不知道在哪里我需要讀取這些數據:讀取是均勻分布的。

在這樣的文件或文件中隨機讀取Java的最快方法是什么? 理想情況下,我應該從幾個不相關的線程進行這些讀取(但如果需要,我可以在單個線程中對讀取進行排隊)。

Java NIO是可行的嗎?

我不熟悉'內存映射文件':我想我不想在內存中映射800 MB。

我想要的只是訪問這些800MB基於磁盤的數據的最快隨機讀取。

順便說一下,如果人們想知道這與我不久前提出的問題完全不同:

Java:基於磁盤的快速哈希集

加載和存儲在內存中的800MB並不多。 如果你有能力讓多核機器在數據集上連續幾天被剝奪,那么你可以支付額外的GB或兩個RAM,不是嗎?

也就是說,閱讀Java的java.nio.MappedByteBuffer 從您的評論中可以清楚地看出“我認為我不想在內存中映射800 MB” ,這個概念並不清楚。

在一個堅果shell中, 映射的字節緩沖區允許以編程方式訪問內存中的數據,盡管它可能在磁盤上或內存中 -這是由操作系統決定的,因為Java的MBB基於操作系統的虛擬內存子系統。 它也很好而且快速。 您還可以安全地從多個線程訪問單個MBB。

以下是我建議您采取的步驟:

  1. 實例化將數據文件映射到MBB的MappedByteBuffer。 創作有點貴,所以請保持它。
  2. 在你的查找方法......
    1. 實例化一個byte[4]數組
    2. 調用.get(byte[] dst, int offset, int length)
    3. 字節數組現在將擁有您的數據,您可以將其轉換為值

並且presto! 你有你的數據!

我是MBB的忠實粉絲,並且過去曾成功地將它們用於此類任務。

RandomAccessFile(阻塞)可能有所幫助: http//java.sun.com/javase/6/docs/api/java/io/RandomAccessFile.html

您還可以使用FileChannel.map()將文件區域映射到內存,然后讀取MappedByteBuffer

另見: http//java.sun.com/docs/books/tutorial/essential/io/rafs.html

實際上800 MB不是很大。 如果您有2 GB或更多內存,則它可以駐留在磁盤緩存中(如果不在您的應用程序本身中)。

對於寫案例,在Java 7上,應該查看AsynchronousFileChannel。

在NTFS上對大文件執行隨機面向記錄的寫入(超過物理內存,因此緩存不能幫助所有內容)時,我發現AsynchronousFileChannel在單線程模式下執行的操作數量是普通FileChannel的兩倍(在10GB上)文件,160字節記錄,完全隨機寫入,一些隨機內容,基准測試循環的幾百次迭代以實現穩定狀態,大約每秒5,300次寫入)。

我最好的猜測是,因為異步io歸結為Windows 7中重疊的IO,所以NTFS文件系統驅動程序能夠在每次調用后不必創建同步點時更快地更新自己的內部結構。

我對RandomAccessFile進行了微基准測試,看看它是如何執行的(結果非常接近FileChannel,並且仍然是AsynchronousFileChannel的一半性能。

不確定多線程寫入會發生什么。 這是在Java 7上,在SSD上(SSD比磁性快一個數量級,在適合內存的較小文件上快一個數量級)。

看看Linux上是否存在相同的比率將會很有趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM