美文网首页
基于zero copy的高效数据传输

基于zero copy的高效数据传输

作者: ic_bbc | 来源:发表于2017-04-16 22:49 被阅读0次

    简介

    在学习kafka如何实现高吞吐量的时候遇到一个技术zero copy,追随kafka文档中的链接深入了解了一下zero copy,在这里mark一下,原文链接https://www.ibm.com/developerworks/linux/library/j-zerocopy/

    通常的实现方式

    假设这样一个场景:从文件中读取数据然后通过网络将数据发送出去,实现的核心部分一般是这样的

    File.read(fileDesc, buf, len);
    Socket.send(socket, buf, len);
    

    尽管实现非常简单,需要4次用户态和内核态的上线文切换,数据需要拷贝4次,整个流程如下图

    Paste_Image.png
    1. read()从用户态切换到内核态,调用sys_read()从文件中读取数据,数据从disk拷贝到内核地址空间
    2. 数据从内核地址空间拷贝到用户地址空间,read函数返回
    3. send函数从用户态切换到内核态,将数据从用户地址空间拷贝到内核地址空间
    4. 数据从内核地址空间拷贝到协议引擎,send函数返回
      使用内核对数据缓存相比于用户直接读取数据好像是低效的,在某些情况下内核态的数据缓存确实会提高效率,但是当数据大小超过内核缓存的大小时,这个操作是低效的。

    zero copy

    其实对于这种场景下,数据没有必要从内核态拷贝到用户态,可以直接从read buffer拷贝到socket buffer,transferTo()函数就是实现这样的操作,但是transferTo函数需要操作系统的支持,在linux下sendfile实现了这样的操作,刚才的实现可以改成下面的:

    transferTo(position, count, writableChannel);
    

    这样数据就不需要从内核空间拷贝到用户空间了

    Paste_Image.png

    如果内核支持gather operations的话还可以进一步优化,在用户实现层面没有发生变化,优化都是在内核实现中的,首先数据从disk拷贝到内核buffer,然后并不需要把数据再次拷贝到socket buffer,只需要把数据位置和长度告诉socket buffer即可,优化之后的数据流如下:

    Paste_Image.png

    性能对比

    Paste_Image.png

    相关文章

      网友评论

          本文标题:基于zero copy的高效数据传输

          本文链接:https://www.haomeiwen.com/subject/efoaattx.html