![](/img/trans.png)
[英]Can multiple RandomAccessFile objects write data to same file?
[英]Why is RandomAccessFile writeLong implemented with multiple write calls?
在分析應用程序時,我注意到RandomAccessFile.writeLong花了很多時間。
我檢查了這個方法的代碼,它涉及8次本機方法寫入調用。 我使用byte []為writeLong編寫了一個替代實現。 像這樣的東西:
RandomAccessFile randomAccessFile = new RandomAccessFile("out.dat", "rwd");
...
byte[] aux = new byte[8];
aux[0] = (byte) ((l >>> 56) & 0xFF);
aux[1] = (byte) ((l >>> 48) & 0xFF);
aux[2] = (byte) ((l >>> 40) & 0xFF);
aux[3] = (byte) ((l >>> 32) & 0xFF);
aux[4] = (byte) ((l >>> 24) & 0xFF);
aux[5] = (byte) ((l >>> 16) & 0xFF);
aux[6] = (byte) ((l >>> 8) & 0xFF);
aux[7] = (byte) ((l >>> 0) & 0xFF);
randomAccessFile.write(aux);
我做了一個小基准測試並得到了這些結果:
使用writeLong():
平均調用時間:91毫秒使用write(byte []):
平均調用時間:11毫秒
在具有Intel(R)CPU T2300 @ 1.66GHz的Linux機器上進行測試
由於本機調用會有一些性能損失,為什么writeLong會以這種方式實現? 我知道應該向太陽隊員提出這個問題,但我希望這里的人有一些提示。
謝謝。
RandomAccessFile.writeLong()似乎不會最小化對OS的調用次數。 通過使用“rwd”而不是“rw”來顯着增加成本,這應該足以表明它本身不需要花費時間。 (事實上,操作系統試圖將每次寫入提交到磁盤,並且磁盤只會旋轉得太快)
{
RandomAccessFile raf = new RandomAccessFile("test.dat", "rwd");
int longCount = 10000;
long start = System.nanoTime();
for (long l = 0; l < longCount; l++)
raf.writeLong(l);
long time = System.nanoTime() - start;
System.out.printf("writeLong() took %,d us on average%n", time / longCount / 1000);
raf.close();
}
{
RandomAccessFile raf = new RandomAccessFile("test2.dat", "rwd");
int longCount = 10000;
long start = System.nanoTime();
byte[] aux = new byte[8];
for (long l = 0; l < longCount; l++) {
aux[0] = (byte) (l >>> 56);
aux[1] = (byte) (l >>> 48);
aux[2] = (byte) (l >>> 40);
aux[3] = (byte) (l >>> 32);
aux[4] = (byte) (l >>> 24);
aux[5] = (byte) (l >>> 16);
aux[6] = (byte) (l >>> 8);
aux[7] = (byte) l;
raf.write(aux);
}
long time = System.nanoTime() - start;
System.out.printf("write byte[8] took %,d us on average%n", time / longCount / 1000);
raf.close();
}
版畫
writeLong() took 2,321 us on average
write byte[8] took 576 us on average
在我看來,你沒有磁盤寫緩存。 沒有磁盤緩存,我希望每個提交的寫入對於5400 RPM磁盤大約需要11毫秒,即60000毫秒/ 5400 => 11毫秒。
我會投票反對懶惰,或者(更加慈善)不考慮后果。
writeLong()
本機實現可能需要每個體系結構的版本,以處理字節排序(JNI將轉換為平台字節順序)。 通過將轉換保持在“跨平台”層,開發人員簡化了移植工作。
至於為什么他們在Java端沒有轉換為數組,我懷疑這是因為害怕垃圾收集。 我猜想RandomAccessFile
自1.1以來已經發生了微小的變化,直到1.3,垃圾收集才開始使小對象分配“免費”。
但是 ,還有RandomAccessFile
的替代方案:看看MappedByteBuffer
編輯:我有一台JDK 1.2.2的機器,從那時起這個方法沒有改變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.