首页 文章

使用sun.misc.Unsafe,从Direct ByteBuffer扫描字节的最快方法是什么?

提问于
浏览
11

BACKGROUND

假设我有一个直接的ByteBuffer:

ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);

并假设我正在将缓冲区传递给AsynchronousSocketChannel以从该套接字读取数据块,一次最多X个字节(此处示例中为1024) .

从套接字到 direct ByteBuffer的传输时间非常棒,因为它全部发生在本机OS内存空间中;我还没有通过JVM "blood-brain"屏障......

QUESTION

假设我的工作是扫描从直接字节缓冲区读回的所有字节,我这样做的最快方法是什么?

我最初问“......利用sun.misc.Unsafe”,但也许这是错误的假设 .

POSSIBLE APPROACHES

我目前看到三种方法,我最感兴趣的是#3:

  • (DEFAULT)使用ByteBuffer的bulk-get将字节直接从本机OS空间拉入内部字节[1024]结构 .

  • (UNSAFE)使用Unsafe的getByte ops直接从ByteBuffer中提取值跳过ByteBuffer的所有边界检查's standard get ops. Peter Lawrey'的答案here似乎表明,不安全的原始本机方法甚至可以由JIT编译器优化("intrinsics" )单机指令导致更加精彩的访问时间 . (=== UPDATE ===有趣的是,对于那些感兴趣的人来说,底层的DirectByteBuffer类看起来就像_1139163那样 . )

  • (BANANAS)在一些犯罪与人类有关的方式中,使用Unsafe,我可以直接将ByteBuffer连接到VM内部存在的字节[1024]的相同内存地址,然后开始使用标准访问数组int索引? (这假设"copyMemory"操作可能会在操作系统级别上做一些非常优化的操作 .

我确实认为,假设copyMemory操作正是它所宣传的内容,即使在更优的操作系统空间中,上面的#2方法可能仍然是最优化的,因为我没有在开始处理之前创建缓冲区的重复项它 .

这与“can I use Unsafe to iterate over a byte[] faster?”问题不同,因为如果没有必要,我甚至不打算在内部将字节拉入byte [] .

谢谢你的时间;只是好奇,如果有人(彼得?)已经疯狂与不安全做这样的事情 .

1 回答

  • 1

    ByteBuffer 方法非常快,因为这些方法是内在函数,VM已将它们映射到非常低级别的指令 . 比较这两种方法:

    byte[] bytes = new byte[N];
        for(int m=0; m<M; m++)
            for(int i=0; i<bytes.length; i++)
                sum += bytes[i];
    
        ByteBuffer bb = ByteBuffer.allocateDirect(N);
        for(int m=0; m<M; m++)
            for(int i=0; i<bb.remaining(); i++)
                sum += bb.get(i);
    

    在我的机器上,差异是0.67ns vs 0.81ns(每个循环) .

    ByteBuffer没有byte []那么快,我有点惊讶 . 但我认为你绝对不应该将它复制到byte []然后访问 .

相关问题