[原]Zero Copy 简介

标签: | 发表时间:2015-03-19 11:44 | 作者:mango_song
出处:http://blog.csdn.net/mango_song

最近在看Kafka的设计原理,kafka在数据传输时采用了zero copy技术:

使用Zero copy方式在内核层直接将文件内容传送给网络Socket,避免应用层数据拷贝,减小IO开销。

关于Zero copy,更多请点击 Efficient data transfer through zero copy


下面是一篇关于zero copy的文章,通俗易懂.

http://blog.csdn.net/zzz_781111/article/details/7534649


许多web应用都会向用户提供大量的静态内容,这意味着有很多data从硬盘读出之后,会原封不动的通过socket传输给用户。这种操作看起来可能不会怎么消耗CPU,但是实际上它是低效的:kernal把数据从disk读出来,然后把它传输给user级的application,然后application再次把同样的内容再传回给处于kernal级的socket。这种场景下,application实际上只是作为一种低效的中间介质,用来把disk file的data传给socket。




data每次穿过user-kernel boundary,都会被copy,这会消耗cpu,并且占用RAM的带宽。幸运的是,你可以用一种叫做Zero-Copy的技术来去掉这些无谓的copy。应用程序用zero copy来请求kernel直接把disk的data传输给socket,而不是通过应用程序传输。Zero copy大大提高了应用程序的性能,并且减少了kernel和user模式的上下文切换。


Java的libaries在linux和unix中支持zero copy,一个关键的api是java.nio.channel.FileChannel的transferTo()方法。我们可以用transferTo()来把bytes直接从调用它的channel传输到另一个writable byte channel,中间不会使data经过应用程序。本文首先描述传统的copy是怎样坑爹的,然后再展示zero-copy技术在性能上是多么的给力以及为什么给力。


Date transfer: The traditional approach


考虑一下这个场景,通过网络把一个文件传输给另一个程序。这个操作的核心代码就是下面的两个函数:


Listing 1. Copying bytes from a file to a socket


File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);
尽管看起来很简单,但是在OS的内部,这个copy操作要经历四次user mode和kernel mode之间的上下文切换,甚至连数据都被拷贝了四次!Figure 1描述了data是怎么移动的。

[基础知识]
DMA=Direct Memory Access。这是一种通过硬件实现的数据传输机制。简单的说,就是不在CPU的参与下完成数据的传输。

CPU copy 。 相比DMA而言,copy的过程需要用到cpu 寄存器等,速度较慢。






Figure 2 描述了上下文切换


Figure 2. Traditional context switches




其中的步骤如下:


read() 引入了一次从user mode到kernel mode的上下文切换。实际上调用了sys_read() 来从文件中读取data。第一次copy由DMA完成,将文件内容从disk读出,存储在kernel的buffer中。
然后data被copy到user buffer中,此时read()成功返回。这是触发了第二次context switch: 从kernel到user。至此,数据存储在user的buffer中。
send() socket call 带来了第三次context switch,这次是从user mode到kernel mode。同时,也发生了第三次copy:把data放到了kernel adress space中。当然,这次的kernel buffer和第一步的buffer是不同的两个buffer。
最终 send() system call 返回了,同时也造成了第四次context switch。同时第四次copy发生,DMA将data从kernel buffer拷贝到protocol engine中。第四次copy是独立而且异步的。
使用kernel buffer做中介(而不是直接把data传到user buffer中)看起来比较低效(多了一次copy)。然而实际上kernel buffer是用来提高性能的。在进行读操作的时候,kernel buffer起到了预读cache的作用。当写请求的data size比kernel buffer的size小的时候,这能够显著的提升性能。在进行写操作时,kernel buffer的存在可以使得写请求完全异步。


悲剧的是,当请求的data size远大于kernel buffer size的时候,这个方法本身变成了性能的瓶颈。因为data需要在disk,kernel buffer,user buffer之间拷贝很多次(每次写满整个buffer)。


而Zero copy正是通过消除这些多余的data copy来提升性能。


Data Transfer:The Zero Copy Approach


如果重新检查一遍traditional approach,你会注意到实际上第二次和第三次copy是毫无意义的。应用程序仅仅缓存了一下data就原封不动的把它发回给socket buffer。实际上,data应该直接在read buffer和socket buffer之间传输。transferTo()方法正是做了这样的操作。Listing 2是transferTo()的函数原型:


public void transferTo(long position, long count, WritableByteChannel target);
transferTo()方法把data从file channel传输到指定的writable byte channel。它需要底层的操作系统支持zero copy。在UNIX和各种Linux中,会执行List 3中的系统调用sendfile(),该命令把data从一个文件描述符传输到另一个文件描述符(Linux中万物皆文件):


#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
在List 1中的file.read()和socket.send()可以用一句transferTo()替代,如List 4:


transferTo(position, count, writableChannel);
Figure 3 展示了在使用transferTo()之后的数据流向






Figure 4 展示了在使用transferTo()之后的上下文切换




在像Listing 4那样使用transferTo()之后,整个过程如下:


transferTo()方法使得文件内容被DMA engine直接copy到一个read buffer中。然后数据被kernel再次拷贝到和output socket相关联的那个kernel buffer中去。
第三次拷贝由DMA engine完成,它把kernel buffer中的data拷贝到protocol engine中。
这是一个很明显的进步:我们把context switch的次数从4次减少到了2次,同时也把data copy的次数从4次降低到了3次(而且其中只有一次占用了CPU,另外两次由DMA完成)。但是,要做到zero copy,这还差得远。如果网卡支持 gather operation,我们可以通过kernel进一步减少数据的拷贝操作。在2.4及以上版本的linux内核中,开发者修改了socket buffer descriptor来适应这一需求。这个方法不仅减少了context switch,还消除了和CPU有关的数据拷贝。user层面的使用方法没有变,但是内部原理却发生了变化:


transferTo()方法使得文件内容被copy到了kernel buffer,这一动作由DMA engine完成。
没有data被copy到socket buffer。取而代之的是socket buffer被追加了一些descriptor的信息,包括data的位置和长度。然后DMA engine直接把data从kernel buffer传输到protocol engine,这样就消除了唯一的一次需要占用CPU的拷贝操作。
Figure 5描述了新的transferTo()方法中的data copy:






作者:mango_song 发表于2015/3/19 9:26:36 原文链接
阅读:4 评论:0 查看评论

相关 [zero copy 简介] 推荐:

[原]Zero Copy 简介

- - 芒果先生Mango的专栏
最近在看Kafka的设计原理,kafka在数据传输时采用了zero copy技术:. 使用Zero copy方式在内核层直接将文件内容传送给网络Socket,避免应用层数据拷贝,减小IO开销. 关于Zero copy,更多请点击 Efficient data transfer through zero copy.

Fate/Zero壁纸第一弹

- 小班 - 和邪社
Fate/Zero自不用多说是目前新番中的佼佼者,可惜这部作品是分拆成了两季来播出的. Fate/Zero的魅力何在呢. 这个问题就很大了,简单点说它是一部集合很多题材优势的作品,穿越、魔幻、历史、爱情,这些你都可以在里面找到,而且最关键的是它融合的非常好. Fate/Zero自不用多说是目前新番中的佼佼者,可惜这部作品是分拆成了两季来播出的.

Zero Install Injector 1.4.1 发布

- ZeeJee - 新闻 - LUPA开源社区
Zero Install Injector是一款很神奇的软件,他的目标是终结Linux下软件安装困难的现象. 通过它你可以非常智能化、自动化的安装任何软件(包括各种打包格 式、源代码),作者自己声称这将会替代其他的软件管理软件:Y.

[转]MapReduce:详解Shuffle(copy,sort,merge)过程

- - 芒果先生Mango的专栏
Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方. 要想理解MapReduce, Shuffle是必须要了解的. 我看过很多相关的资料,但每次看完都云里雾里的绕着,很难理清大致的逻辑,反而越搅越混. 前段时间在做MapReduce job 性能调优的工作,需要深入代码研究MapReduce的运行机制,这才对Shuffle探了个究竟.

从Google+学到的,先复制,再创新(Copy First, Innovate Second)

- 断肠君 - 36氪
相对于从头发明社交网络,Google+只是复制了其他流行社交网络最好的部分,我猜这也是为什么它会在短时间内如此流行的原因. 每个人都在使用Facebook的布局,那么为什么不降低人们的使用成本,把布局弄成一样呢. Facebook的Like按钮. Google注意到人们真的喜欢Facebook的Like功能,发一条评论真的是很艰难的工作,但是让人们通过轻轻点击一下来表达一个反馈是很容易的.

Carbon Copy Cloner – 智能磁盘克隆 [Mac] | 小众软件 > Mac

- zypatroon - 小众软件
Carbon Copy Cloner 简称 CCC,是 Mac 上硬盘克隆、同步、备份的最佳工具. 计划任务、增量备份、整盘克隆恢复,这些常规功能不在话下. 软件设计的初衷就是智能到让人忘记它的存在. 界面简单、易于配置,但后台各种强大,甚至可设定插上某个移动硬盘时自动开始备份. 下载(5.2MB): 官网 | 下载 | 来自小众软件.

温故而知新「Fate/Zero」 PV+CM大回顾

- Adam - 和邪社
凌晨备受关注的10月新番《Fate/Zero》就要在nico上做8字幕全球放送了,在正是面相大家前. 大家再来回顾一下此前Fate/Zero为了宣传造势而制作的两段PV和连续7弹的CM吧.

Fate/Zero分拆两季播出BD-BOX添加未删减版

- Adam - 和邪社
11月出版的Newtype报道,Fate/Zero的BC-BOX将包含有TVA中被删除的一些画面和镜头. 此外26集的Fate/Zero将分叉成两季来播出,理由就是为了保证作品的质量.

ஐ 2011年秋番:Fate/Zero「英靈背景」Ⅱ

- MDJ - 模物語
★★ 不想被擊中者,請勿點閱. 吉爾伽美什(Gilgamesh ). 人類最古的敘事詩“吉爾伽美什敘事詩”裡所講述的偉大的王. 被認為是追溯到距今約5000年,治理著古代美索不達米亞蘇美爾王朝的都市國家烏魯克的實際存在的王. 但大部分文獻中,吉爾伽美什雖被標示為神明,但並無證據顯示他當時已被神化,而根據有關吉爾伽美什的神話來看,應是後世的人所編製的.

树莓派最新开发主板Zero仅售$5(约合¥31)

- - CnBeta.COM
过去数年间树莓派基金会通过和大学和爱好者的互动合作基于可负担的开发主板来创造各种DIY计算机项目. 今天公司宣布推出最新的可编程计算机主板--树莓派Zero,售价仅仅只有$5(约合¥31). 该开发主板采用Broadcom BCM 2835应用处理器(1GHz的ARM11核心),512MB的内存,MicroSD卡扩展,支持1080P(60fps)的mini-HDMI端口,Micro-USB端口,和更大树莓派相同的pin布局.