mur*_*ngu 2 jvm nio filechannel irq dma
为什么java.nio.FileChannel transferTo()和transferFrom()比一些JVM/OS组合上的逐字节传输(基于流或使用ByteBuffer)更快?
这些方法是否使用直接内存访问(DMA)而不是为每个字节传输发出中断请求(IRQ)?
小智 5
这些方法是否使用直接内存访问(DMA)而不是为每个字节传输发出中断请求(IRQ)?
具体细节取决于实际实现,并且不需要使用任何特定机制.这在transferTo(强调我的)文档中暗示:
此方法可能比从此通道读取并写入目标通道的简单循环更有效.许多操作系统可以直接从文件系统缓存向目标通道传输字节,而无需实际复制它们.
'可能','很多'......所以没有保证.
假设使用该方法可能更有效,因为您允许JVM快速浏览本机代码(如果使用支持的通道类型),那么它确实更有效.他们描述的"简单循环"的工作方式如下:
ByteBuffer buf = ByteBuffer.allocateDirect(BUF_SIZE);
while ( /* read more condition */ ) {
source.read(buf);
buf.flip();
target.write(buf);
buf.compact();
}
Run Code Online (Sandbox Code Playgroud)
请注意,即使此代码段使用直接缓冲区,您仍然需要重新使用Java进行缓冲区管理(读取,翻转,写入,压缩).优化编译器可能能够忽略其中的一些,但它可能不会.
但是,使用transferTo/ transferFrom将其留给JVM来决定如何传输字节.如果平台本身支持此类传输,则可以在不创建中间缓冲区的情况下执行此操作.如果没有这样的支持,JVM仍然可以实现如上所述的循环.
示例:假设SocketChannel被告知直接从FileChannel读取数据transferFrom.最近读取了FileChannel,其内容位于OS文件缓存中.SocketChannel可以直接指向OS文件缓存并从那里开始传输,而不是将字节读取并复制到缓冲区中.消除了至少一轮复制.
现在进一步假设套接字(A)实际上连接到某个其他本地进程,例如使用一种名为SocketChannel B的管道.当B开始读取它从A获取的内容时,它实际上可能是直接从OS文件中读取再次缓存.如果那么B只是用于transferTo另一个频道......你明白了.
| 归档时间: |
|
| 查看次数: |
3341 次 |
| 最近记录: |