0
点赞
收藏
分享

微信扫一扫

Nginx I/O优化之 sendfile 零拷贝

冬冬_79d4 2022-08-17 阅读 47


Nginx I/O优化之 sendfile 零拷贝_系统调用

 

指令说明

语法: sendfile on | off;
默认值: sendfile off;
上下文: http,server,location,if in location

指定是否使用sendfile系统调用来传输文件。
sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。

 

原理解释

read/write

Nginx I/O优化之 sendfile 零拷贝_系统调用_02

在传统的文件传输方式(read、write/send方式),具体流程细节如下:

  1. 调用read函数,文件数据拷贝到内核缓冲区(磁盘高速缓存)
  2. read函数返回,数据从内核缓冲区拷贝到用户缓冲区
  3. 调用write/send函数,将数据从用户缓冲区拷贝到内核socket缓冲区
  4. 数据从内核socket缓冲区拷贝到协议引擎中

在这个过程当中,文件数据实际上是经过了四次拷贝操作:硬盘—>内核缓冲区—>用户缓冲区—>内核socket缓冲区—>协议引擎

 

sendfile(减少进程间切换,减少拷贝次数)

sendfile系统调用则提供了一种减少拷贝次数,提升文件传输性能的方法。

  1. sendfile系统调用利用DMA引擎将文件数据拷贝到内核缓冲区,之后数据被拷贝到内核socket缓冲区中
  2. DMA引擎将数据从内核socket缓冲区拷贝到协议引擎中

这里没有用户态和内核态之间的切换,也没有内核缓冲区和用户缓冲区之间的拷贝,大大提升了传输性能。(实际上只调用了sendfile,sendfile告诉要从哪个文件,哪个字节开始读取,读取多少个字节。将读取出来的字节发送到哪个socket上面,相当于正常情况下减少了拷贝次数。)
这个过程数据经历的拷贝操作:硬盘—>内核缓冲区—>内核socket缓冲区—>协议引擎

Nginx I/O优化之 sendfile 零拷贝_nginx_03

 

带有DMA收集拷贝功能的sendfile

对于带有DMA收集拷贝功能的sendfile系统调用,还可以再减少一次内核缓冲区之间的拷贝。具体流程如下:

  1. sendfile系统调用利用DMA引擎将文件数据拷贝到内核缓冲区,之后,将带有文件位置和长度信息的缓冲区描述符添加到内核socket缓冲区中
  2. DMA引擎会将数据直接从内核缓冲区拷贝到协议引擎中

这个过程数据经历的拷贝操作:硬盘—>内核缓冲区—>协议引擎

 

sendfile 直接I/O 异步I/O同时开启???

注意:sendfile当启用directio的时候,directio会禁用sendfile,diectio更加适合大文件。 

#当文件大小超过8M,启动AIO和directio
location /video/ {
sendfile on;
aio on;
directio 8m;
}

 

加餐(I/O优化:零拷贝技术)

上面的工作线程,从磁盘读文件、再通过网络发送数据,数据从磁盘到网络,兜兜转转需要拷贝四次,其中CPU亲自搬运都需要两次。

Nginx I/O优化之 sendfile 零拷贝_零拷贝_04

零拷贝技术,解放CPU,文件数据直接从内核发送出去,无需再拷贝到应用程序缓冲区,白白浪费资源。

Nginx I/O优化之 sendfile 零拷贝_零拷贝_05

Linux API:

ssize_t sendfile(
int out_fd,
int in_fd,
off_t *offset,
size_t count
);

函数名字已经把函数的功能解释的很明显了:发送文件。指定要发送的文件描述符和网络套接字描述符,一个函数搞定!用上了零拷贝技术后开发了2.0版本,图片加载速度明显有了提升。

举报

相关推荐

0 条评论