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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章