我必须在Java中编写一个外部排序算法,只使用JVM RAM(基本上,我不能映射文件)。所以我要做的第一部分是从文件中读取数据。
我找到了this tutorial。
问题是该教程是关于阅读byte
的,我必须阅读int
。我不确定IntBuffer
是如何实现的,但我认为它是一个字节缓冲区的包装器。鉴于这一事实,我是对的,我能做的最快的事情是使用教程中的“FileChannel with direct ByteBuffer and byte array”方法(下面的代码),然后用int
创建单独的数组,我使用位操作“手动”从字节中获取?
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浪费了很多时间),我应该使用完全不同的方法,还是在一个线程中使用此方法并进行排序另一个线程好方法?我真的想为每一纳秒的性能而战。
答案 0 :(得分:1)
new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
然后使用readInt()。这将与使用FileChannels缺少映射文件的任何操作一样快,并且它们比普通I / O快约20%。
直接字节缓冲区对此无效。当您不想自己查看或修改数据时,它们非常有用,您只需在通道之间进行复制。它保存数据不会越过JNI / Java边界两次,只需将其保留在JNI层内。不适用于这种情况。
答案 1 :(得分:1)
如果你想争取纳秒级的性能,请购买速度更快的磁盘,例如使用SSD或RAID N或两者。 SSD驱动器可以将数据传输速度比移动磁盘快10倍。这将远远超过您在Java中可以做的任何事情。