前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >零拷贝( Zore Copy )

零拷贝( Zore Copy )

作者头像
兜兜毛毛
发布2021-01-18 10:36:28
7140
发布2021-01-18 10:36:28
举报
文章被收录于专栏:兜兜毛毛

零拷贝是实现高速数据传输的一种协议。数据从源节点传送到目的节点的过程中不经过中间缓存。

具体提高了哪些需要我们先来了解传统IO的方式,通过与传统IO方式对比来看。

传统IO方式

在java开发中,从某台机器将一份数据通过网络传输到另外一台机器,大致的代码如下:

代码语言:javascript
复制
Socket socket = new Socket(HOST, PORT);
InputStream inputStream = new FileInputStream(FILE_PATH);
OutputStream outputStream = new DataOutputStream(socket.getOutputStream());

byte[] buffer = new byte[4096];
while (inputStream.read(buffer) >= 0) {
    outputStream.write(buffer);
}

outputStream.close();
socket.close();
inputStream.close();

看起来代码很简单,但如果我们深入到操作系统层面,就会发现实际的微观操作更复杂。具体操作如下图:

代码语言:javascript
复制
1. 用户进程向OS发出read()系统调用,触发上下文切换,从用户态转换到内核态。
2. CPU发起IO请求,通过直接内存访问(DMA)从磁盘读取文件内容,复制到内核缓冲区PageCache中
3. 将内核缓冲区数据,拷贝到用户空间缓冲区,触发上下文切换,从内核态转换到用户态。
4. 用户进程向OS发起write系统调用,触发上下文切换,从用户态切换到内核态。
5. 将数据从用户缓冲区拷贝到内核中与目的地Socket关联的缓冲区。
6. 数据最终经由Socket通过DMA传送到硬件(网卡)缓冲区,write()系统调用返回,并从内核态切换回用户态。

零拷贝(Zero-copy)

以下使用FileChannel.transferTo方法,实现zero-copy:

代码语言:javascript
复制
SocketAddress socketAddress = new InetSocketAddress(HOST, PORT);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(socketAddress);

File file = new File(FILE_PATH);
FileChannel fileChannel = new FileInputStream(file).getChannel();
fileChannel.transferTo(0, file.length(), socketChannel);

fileChannel.close();
socketChannel.close();

相比传统方式,零拷贝的执行流程如下图:

可以看到,相比传统方式,零拷贝不走数据缓冲区减少了一些不必要的操作。

零拷贝的应用

零拷贝在很多框架中得到了广泛使用,常见的比如Netty、Kafka等等。

在kafka中使用了很多设计思想,比如分区并行、顺序写入、页缓存、高效序列化、零拷贝等等。

上边博客分析了Kafka的大概架构,知道了kafka中的文件都是以.log文件存储,每个日志文件对应两个索引文件.index与.timeindex。

kafka在传输数据时利用索引,使用fileChannel.transferTo(position, count, socketChannel)指定数据位置与大小实现零拷贝。

kafka底层传输源码:(TransportLayer)

代码语言:javascript
复制
  /**
     * Transfers bytes from `fileChannel` to this `TransportLayer`.
     *
     * This method will delegate to {@link FileChannel#transferTo(long, long, java.nio.channels.WritableByteChannel)},
     * but it will unwrap the destination channel, if possible, in order to benefit from zero copy. This is required
     * because the fast path of `transferTo` is only executed if the destination buffer inherits from an internal JDK
     * class.
     *
     * @param fileChannel The source channel
     * @param position The position within the file at which the transfer is to begin; must be non-negative
     * @param count The maximum number of bytes to be transferred; must be non-negative
     * @return The number of bytes, possibly zero, that were actually transferred
     * @see FileChannel#transferTo(long, long, java.nio.channels.WritableByteChannel)
     */
    long transferFrom(FileChannel fileChannel, long position, long count) throws IOException;

实现类(PlaintextTransportLayer):

代码语言:javascript
复制
@Override
 public long transferFrom(FileChannel fileChannel, long position, long count) throws IOException {
      return fileChannel.transferTo(position, count, socketChannel);
 }

该方法的功能是将FileChannel中的数据传输到TransportLayer,也就是SocketChannel。在实现类PlaintextTransportLayer的对应方法中,就是直接调用了FileChannel.transferTo()方法。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 传统IO方式
  • 零拷贝(Zero-copy)
  • 零拷贝的应用
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档