背景
假设我有一个直接字节缓冲区:
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);
假设我将缓冲区传递给AsynchronousSocketChannel,以从套接字读取数据块,每次读取X个字节(例如此处的1024个字节)。
将套接字中的数据转移到直接 ByteBuffer 中的传输时间非常快,因为它全部发生在本机操作系统内存空间中;我还没有穿过 JVM 的“血脑屏障”...
问题
假设我的工作是扫描从直接字节缓冲区中读取的所有字节,那么我最快的方法是什么?
我最初问了“...利用sun.misc.Unsafe”,但可能这是错误的假设。
可能的方法
我目前看到三种方法,我最感兴趣的是第3种:
- (默认) 使用ByteBuffer的bulk-get从本机操作系统空间直接拉取字节到内部byte[1024]结构中。
- (不安全) 使用Unsafe的getByte操作直接从ByteBuffer中提取值,跳过了ByteBuffer标准get操作的所有边界检查。Peter Lawrey在此处的答案似乎表明,这些 Unsafe 中的原始本机方法可以被 JIT 编译器(“内部函数”)优化为单个机器指令,从而导致更快速的访问时间。 (===更新===有趣的是,对于那些感兴趣的人,底层的DirectByteBuffer类正是使用这种方式进行get/put操作的。)
- (香蕉) 以某种违反人类罪行的方式,使用Unsafe,我可以将直接ByteBuffer的内存区域复制到VM中存在于byte[1024]相同内存地址上,并开始使用标准int索引访问该数组?(这使得“copyMemory”操作可以在 OS 级别上进行一些奇妙的优化假设。)
我想到了一个假设,即假设“copyMemory”操作确实做到了它所宣称的,即使在更优化的操作系统空间中,以上述第2种方法仍然是最优化的,因为我在开始处理它之前没有创建缓冲区的副本。
这与“我能否使用Unsafe更
sum
的值?否则JIT会将其优化掉。我认为每个循环0.67ns和0.81ns非常快,也许它确实是那么快,但我对此有点好奇。 - skiwi0
) - ZhongYu