在对应用程序进行性能分析时,我注意到RandomAccessFile.writeLong需要很多时间。

我检查了此方法的代码,它涉及本地方法write的八个调用。
我使用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?
我知道应该向Sun公司提出这个问题,但是我希望这里的人有一些提示。

谢谢。

最佳答案

我会投票赞成懒惰,或者(更慈善)不考虑后果。
writeLong()的本机实现可能会为每种体系结构要求版本,以处理字节顺序(JNI将转换为平台字节顺序)。通过将翻译保留在“跨平台”层中,开发人员简化了移植工作。

至于为什么它们在Java端没有转换为数组,我怀疑这是由于担心垃圾回收。我猜想RandomAccessFile自1.1以来变化很小,直到1.3垃圾回收才开始使小对象分配“免费”。

但是,除了RandomAccessFile之外,还有另一种选择:看看MappedByteBuffer
编辑:我有一台使用JDK 1.2.2的计算机,此方法此后没有更改。

07-24 09:25