![](/img/trans.png)
[英]How do you write to disk (with flushing) in Java and maintain performance?
[英]Java Performance - How to write big array to disk/sdcard with high performance?
有沒有辦法在Java中向磁盤寫入一大堆,比如整數? 我在Android上這樣做,並沒有找到任何接近本機C代碼的方法。
生成的文件不需要可移植到具有不同表示的不同機器,因此邏輯上只是對底層字節的批量寫入就足夠了。 但我不知道如何從Java有效地做到這一點。
我試過在網上搜索,並測試了以下內容:
提前致謝
NIO代碼:
int[] array = new array[10000000];
...
raf = new RandomAccessFile(ti.testFileName, "rw");
chan = raf.getChannel();
MappedByteBuffer out = chan.map(FileChannel.MapMode.READ_WRITE, 0, array.length*4);
ib = out.asIntBuffer();
ib.put(array);
out.force();
raf.close();
你說它很慢但速度很可能取決於磁盤子系統的速度。 您應該能夠在大約半秒內將40 MB寫入常規磁盤以提交到磁盤。
以下使用NIO,在工作站上寫入需要665 ms,在工作站上需要62 ms。 讀取和寫入會使相同數量的數據混亂,但讀取可以從OS緩存中獲取數據,這與寫入磁盤所需的時間不同。
int[] ints = new int[10 * 1000 * 1000];
long start = System.nanoTime();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(ints.length*4+4);
byteBuffer.putInt(ints.length);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(ints);
byteBuffer.position(0);
FileChannel fc = new FileOutputStream("main.dat").getChannel();
fc.write(byteBuffer);
fc.force(false);
fc.close();
long time = System.nanoTime() - start;
System.out.println("Write time " + time / 1000 / 1000 + " ms.");
long start2 = System.nanoTime();
FileChannel fc2 = new FileInputStream("main.dat").getChannel();
ByteBuffer lengthBuffer = ByteBuffer.allocate(4);
while(lengthBuffer.remaining()>0) fc2.read(lengthBuffer);
int length = lengthBuffer.getInt(0);
int[] ints2 = new int[length];
ByteBuffer buffer2 = ByteBuffer.allocateDirect(length*4);
while(buffer2.remaining()>0 && fc2.read(buffer2) > 0);
buffer2.flip();
buffer2.asIntBuffer().get(ints2);
long time2 = System.nanoTime() - start2;
System.out.println("Read time " + time2 / 1000 / 1000 + " ms.");
我已將長度添加到文件的開頭,因此不必假設它。 順便說一下:我修復了寫中的錯誤。
我不知道Android實現,但在標准Java中,良好的老式IO通常優於NIO。
例如,如果你有一個字節數組,我相信下面的代碼應該相對較快:
byte[] bytes = new byte[10000];
// ...
FileOutputStream out = new FileOutputStream(...);
try {
out.write(bytes);
} finally {
out.close();
}
請記住,這將阻塞,直到寫入整個字節數組。 但是你沒有說明非阻塞行為是否存在問題。
你沒有提到的另一件事是你打算在寫入文件時如何編碼整數。 您需要在寫入文件之前在內存中執行編碼,但是數組可能太大而無法一次編碼所有內容,在這種情況下,您可以使用幾百K的塊進行編碼/寫入。
彼得,
當事情看起來好得令人難以置信時,通常情況就是如此。 寫入40MB數據的89msecs表明你的硬盤帶寬要大得多500MB /秒(因為你還包括打開和關閉文件的時間)。 這不可能是真的。 你檢查的文件實際上是40MB大小。 另外,我建議您初始化緩沖區以查看文件內容不是全部為零。 可能是一個未被觸及的緩沖區,只是跳過了。 不管它是什么,你擁有的數字太好了,不可能成真。
謝謝。
考慮一下緩沖輸出流
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.