netty零拷贝

原文:https://learn.lianglianglee.com/专栏/Netty 核心原理剖析与 RPC 实践-完/16 IO 加速:与众不同的 Netty 零拷贝技术.md

此地址下的 【专栏】-> 【netty】https://learn.lianglianglee.com
参考:

  1. https://www.jianshu.com/p/a199ca28e80d
  2. https://zhuanlan.zhihu.com/p/76059333
  3. https://segmentfault.com/a/1190000022790435
  4. https://zhuanlan.zhihu.com/p/78335525
  5. https://blog.csdn.net/weixin_48726650/article/details/107664915
  6. http://dockone.io/article/10019

如果要把磁盘上一个文件发送给网络上某台主机,那么:
Linux:disk -> kernel(dma) -> user context(cpu) -> socket buffer(cpu) -> nic(dma) 一共4次
Linux 2.4之前:sendfile()系统调用直接将kernel buffer 复制给socket buffer,一共3次
Linux 2.4之后:sendfile()系统调用直接将kernel buffer复制给nic buffer,一共2次,并且,cpu参与复制的两次都被干掉了
所谓零拷贝,并不是无拷贝,而是不需要cpu参与的拷贝,其中的两次是必须要做的(dma在做),好像不能直接从disk拷贝到nic(比如网卡缓存),从广义上说零拷贝是说,只要减少拷贝次数就是零拷贝,比如这里只要少于4次就是
上面sendfile是2次拷贝,而mmap是3次拷贝,mmap和sendfile都是零拷贝的实现方式,Java对二者均有实现,分别是transferTo/transferFrom实现sendfile和channel.map()实现mmap,
上述方式对于固定文件的发送没问题,但是如果希望在发送文件的时候能够修改文件,那么就不好使,此时就需要使用mmap,将文件映射到内核地址空间,并且用户空间也共享这一段内存,
那么就需要3次拷贝(2次dma,分别是disk->kernel buffer,socket buffer -> nic buffer,一次cpu从内核空间拷贝到socket buffer)以及4次上下文切换,此时的内核空间其实就是page cache,
修改pagecache如果不发生缺页中断那么性能是相当高的,rocketmq就是这样来实现comsulequeue和commitlog的

netty零拷贝,有5方面

  1. 全部使用直接内存,这样一来就可以避免jvm堆内存copy数据到kernel内存
  2. CompositeBuf,可以拼接多个ByteBuf,并且底层并附copy,而是引用拼接
  3. wrap操作合并多个ByteBuf,也无需copy
  4. slice分割ByteBuf,也无需copy,底层共用一个buf
  5. 使用Java transferTo/transferFrom(底层调用sendfile())来实现无需cpu拷贝

RocketMQ零拷贝:mmap + write

kafka零拷贝:mmap + sendfile
1、partition顺序读写,充分利用磁盘特性,这是基础;
2、Producer生产的数据持久化到broker,采用mmap文件映射,实现顺序的快速写入;
3、Customer从broker读取数据,采用sendfile,将磁盘文件读到OS内核缓冲区后,直接转到socket buffer进行网络发送。

RocketMQ和kafka零拷贝区别:https://blog.csdn.net/weixin_48726650/article/details/107664915

原文地址:https://www.cnblogs.com/dreamroute/p/15762658.html