专栏名称: hryou0922
目录
相关文章推荐
主编温静  ·  主编温静丨今天发生了什么? ·  15 小时前  
CHINADAILY  ·  World丨Strike hits ... ·  昨天  
新京报评论  ·  每一个代表,都是一座桥梁 | 两会观察 ·  2 天前  
CHINADAILY  ·  Life丨Lights, camera, ... ·  2 天前  
51好读  ›  专栏  ›  hryou0922

系统设计 - Zero-Copy总结和性能测试

hryou0922  · 掘金  ·  · 2019-07-08 17:03

正文

阅读 13

系统设计 - Zero-Copy总结和性能测试

zero-copy应用场景

应用场景:将本地一个文件通过网络传输给另一个程序 关键字: 数据复制过程中,内容不进行修改

zero-copy技术的使用场景有很多,比如Kafka, 又或者是Netty等,可以大大提升程序的性能 下面我们通过对比传统方式和zero-copy的方式传输数据,来理解zero-copy。

传统方式传输数据

代码如下:

// 将文件读取到buf中 
File.read(fileDesc, buf, len);
// 将buf中的数据写入到socket中
Socket.send(socket, buf, len);
复制代码

结合下图理解理解操作如下:

在这里插入图片描述
在这里插入图片描述
详细步骤如下 : 1. 调用File.read()方法会发生上下文切换(context switch),从user mode切换到kernel mode。在read()内部会调用sys_read()来从文件中读取数据。第一次copy由DMA (direct memory access)完成,将文件内容从磁盘读出,并存储在kernel空间的buffer中,为方便说明,这个buffer称为reader buffer。 2. 然后请求的数据被从kernel空间的buffer copy到user buffer中,这是第二次copy。调用的返回又触发了第二次上下文切换,从kernel mode返回到user mode。至此,数据存储在user buffer中。 3. Socket.send()会触发了第三次上下文切换,从user mode到kernel mode,并执行第三次copy,将数据从user buffer重新复制到kernel的buffer中。当然,这次的kernel buffer和第一步的kernel buffer不是同一个buffer,这次buffer和目标socket关联,命名为socket buffer。 4. 完成copy后,Socket.send()返回时,同时也造成了第四次上下文切换。同时第四次copy发生,DMA egine将数据从kernel buffer复制到网卡设备(protocol engine)中。第四次copy是独立而且异步的。

结论 : 以上操作要经历4次user mode和kernel mode之间的上下文切换,数据都被拷贝了4次。通过上面的分析,我们发现第2步和第3步数据copy是多余,系统完全可以将文件读取到kernel buffer中后,直接将kernel buffer中的数据写入socket。为了实现这个优化,linux引入了zero copy。







请到「今天看啥」查看全文