日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

异步IO实现和应用场景

發(fā)布時(shí)間:2023/12/10 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步IO实现和应用场景 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

學(xué)習(xí)自用,還有很多不足的地方

異步IO和同步IO

當(dāng)網(wǎng)卡有了數(shù)據(jù),DMA會(huì)把數(shù)據(jù)拷貝到內(nèi)核緩沖區(qū)(內(nèi)核緩沖區(qū)的哪里呢);而從內(nèi)核緩沖區(qū)拷貝到用戶態(tài)需要用戶調(diào)用read,同步地進(jìn)行

異步則是注冊(cè)個(gè)讀完成事件,等其他用戶態(tài)線程/內(nèi)核進(jìn)程拷貝到用戶態(tài)后再提醒

aio最核心的需求就是解偶submit和wait for completion, 簡(jiǎn)單地說就是在submit的時(shí)候不要阻塞, 這樣用戶在submit之后可以做其它事情或者繼續(xù)submit新的io, 從而獲得更高的cpu利用率和磁盤帶寬.

異步IO的好處

  • 同步read從內(nèi)核區(qū)拷貝到用戶態(tài)需要等待短暫的時(shí)間,全異步的aio_read不存在這個(gè)短暫時(shí)間(同步read的系統(tǒng)調(diào)用和從內(nèi)核拷貝到用戶的時(shí)間),效率更高;異步IO一個(gè)例子就是nginx的讀文件的操作(?)
  • 那在內(nèi)核上處理的真正異步io的優(yōu)勢(shì)在于:和同步非阻塞io相比,優(yōu)勢(shì)主要在于不用維護(hù)數(shù)據(jù)讀不齊時(shí)的邏輯處理(可能是等到讀齊了再通知吧)
  • 異步IO的壞處

  • 要提前規(guī)定好緩沖區(qū)大小以在數(shù)據(jù)到來時(shí)自動(dòng)拷貝,如果設(shè)置太大會(huì)浪費(fèi),太小又有問題,而同步IO可以在讀取時(shí)適時(shí)增加和釋放空間,比如muduo就在read的同時(shí)用writev增加棧上buffer大小
  • 另外異步IO的編程會(huì)麻煩一點(diǎn),調(diào)用aio_read后還要有等待完成讀取的邏輯,看看nginx里面文件操作就知道用起來多痛苦了(不過應(yīng)該可以優(yōu)化,用promise/future或await來優(yōu)化?..那實(shí)現(xiàn)得更麻煩了)
  • Linux的AIO

  • POSIX的AIO(應(yīng)該就是glic的aio),是用pthread實(shí)現(xiàn)的用回調(diào)或signal通知的,沒有connect,accept等網(wǎng)絡(luò)IO的API
  • ?kernel 的 aio,即kernel native AIO,被用在了nginx上,有一個(gè)封裝libaio,一開始是為了數(shù)據(jù)庫(kù)涉及的,所以只能以 O_DIRECT 方式做直接 IO,即跳過page cache直接寫入磁盤(數(shù)據(jù)庫(kù)應(yīng)用這種實(shí)現(xiàn)如INNODB,它在應(yīng)用層實(shí)現(xiàn)自己的cache機(jī)制而不用OS的page cache),這就導(dǎo)致一些問題如data buffer的對(duì)齊,它要求讀寫的的大小和偏移要以區(qū)塊的方式對(duì)齊即offset與size的對(duì)齊(都是啥啊?),估計(jì)普通用戶不會(huì)愿意觸及這個(gè)。除了數(shù)據(jù)庫(kù)的開發(fā)者。而且網(wǎng)絡(luò)API一樣沒有。另外kernel native AIO存在額外的開銷,每個(gè)IO提交需要拷貝64+8字節(jié),每個(gè)IO完成需要拷貝32字節(jié),這在某些場(chǎng)景下影響很可觀。在使用完成event的時(shí)候需要非常小心,否則容易丟事件。IO總是需要至少2個(gè)系統(tǒng)調(diào)用(submit + wait-for-completion),在spectre/meltdown開啟下性能下降非常嚴(yán)重。
  • 還有一個(gè)libev作者搞的libeio,在beta階段,設(shè)計(jì)上汲取了前兩個(gè)的經(jīng)驗(yàn)用了一些tricky的辦法,也是用線程在用戶態(tài)模擬的,bug更少但是代碼更難看懂。封裝了大量的文件API ,但也沒有網(wǎng)絡(luò)API。而且有bug的,不能用在 socket 讀寫上,而且不會(huì)返回顯式錯(cuò)誤,而是自動(dòng)切成非異步 IO
  • 最新內(nèi)核引入的io_uring可能可以統(tǒng)一網(wǎng)絡(luò)和磁盤的aio模式。
  • AIO實(shí)現(xiàn)

    AIO復(fù)制數(shù)據(jù)從內(nèi)核態(tài)到用戶態(tài)的時(shí)候,可能會(huì)發(fā)生一些問題阻塞住,如申請(qǐng)用戶態(tài)的空間不夠,請(qǐng)求隊(duì)列slot和inode的semaphore(是啥?)

    用何種方式來提醒讀寫完成呢,

    • 信號(hào)IO不僅在大量IO操作時(shí)可能會(huì)因?yàn)樾盘?hào)隊(duì)列溢出導(dǎo)致沒法通知(?)
    • 定義一個(gè)回調(diào)函數(shù),用sigfd也可以,則需要用eventloop來進(jìn)行監(jiān)聽,復(fù)雜的話可以用promise/future來簡(jiǎn)化語法
    • Filesystem/Buffered AIO: Buffered IO與Direct IO的資源沖突和數(shù)據(jù)完整問題(??)

    內(nèi)核線程來或者單獨(dú)用一個(gè)線程進(jìn)行read操作,(用多線程會(huì)有多個(gè)讀一個(gè)fd的問題),要維護(hù)read的隊(duì)列,傳入讀出來存的地方

    猜想

    猜想:如果大量不斷的連接到來事件然后斷開...

    listen socket的可讀事件,消息socket可讀事件,如果讓其中一個(gè)單獨(dú)用一個(gè)線程異步處理,則開銷是:邏輯復(fù)雜度,另外的線程開銷,活躍線程多的情況會(huì)有切換開銷,好處是IO線程不需要用到系統(tǒng)調(diào)用read,IO線程阻塞時(shí)間變少

    猜想:如果大量不斷到來然后發(fā)送一小段東西然后斷開...

    同理上面吧,這樣的場(chǎng)景更適合異步,因?yàn)閞ead時(shí)間更長(zhǎng),不過如果一直是消息到來事件,瓶頸就在CPU上,那個(gè)異步線程畢竟也是單核處理,如果夾雜著其他不耗時(shí)事件到來,這些事件響應(yīng)可能會(huì)變高

    異步更高效的場(chǎng)景

    IO線程做的事:epoll_wait->分發(fā)事件;

    如果是大量socket的大量數(shù)據(jù)且到來,則read耗時(shí)長(zhǎng),總結(jié)下兩個(gè)缺點(diǎn):

  • 同步read會(huì)阻塞epoll_wait的調(diào)用,也就延遲了socket的處理,假如同時(shí)夾雜著不耗時(shí)的socket連接到來事件則客戶端響應(yīng)會(huì)變慢;只能通過每個(gè)只讀少量大小的方式來保證socket的及時(shí)處理,但這樣不管是LT或ET+robin list都會(huì)增加額外系統(tǒng)調(diào)用開銷或應(yīng)用復(fù)雜度;
  • read操作從內(nèi)核搬數(shù)據(jù)到用戶態(tài)無法利用多核,實(shí)現(xiàn)得好的話,可以讓多個(gè)異步來處理異步IO(多個(gè)異步線程這樣實(shí)現(xiàn)應(yīng)該會(huì)難吧,還會(huì)有跨線程讀同一個(gè)fd的問題,如果用epoll_oneshot來解決還會(huì)有epoll_ctl系統(tǒng)調(diào)用的性能損耗);單核CPU當(dāng)然是同步更高效;
  • 綜上:多核下的大量socket的大量數(shù)據(jù)(夾雜著大量耗時(shí)少的事件如連接到來事件應(yīng)該更明顯),應(yīng)該是異步IO的QPS更高(連接到來的socket和大量數(shù)據(jù)的socket事件響應(yīng),應(yīng)不應(yīng)該分開來算啊?)

    同步更高效的場(chǎng)景

    單核情況下,用異步會(huì)多一次上下文切換和一些多出來的步驟

    TODO

  • 為什么linux難以實(shí)現(xiàn)異步IO,寫完了還不是很懂
  • 光明說的,AIO有多個(gè)線程操作,第一次事件用AIO_read,但是沒被及時(shí)處理,因?yàn)長(zhǎng)T,所以下次再出發(fā)再調(diào)用aio_read,線程不同了會(huì)有問題吧,也就是多線程處理epoll事件的問題,epoll還提供了oneshot這個(gè)標(biāo)志位?...又說好像問題不大,不過和其他場(chǎng)景可能有問題,就是跟oneshot的問題是一樣的
  • 參考資料

  • Linux上沒有真正的異步,為什么服務(wù)器還是用Linux的多? - 知乎 https://www.zhihu.com/question/41706901
  • linux下的異步IO(AIO)是否已成熟? - 知乎 https://www.zhihu.com/question/26943558
  • 如何深刻地理解 Unix/Linux 中同步 IO 和異步 IO? - 知乎 https://www.zhihu.com/question/352921402
  • 為什么Linux下沒有真正的異步IO模型? - 知乎 https://www.zhihu.com/question/421584363
  • 吐槽linux,AIO的https://www.aikaiyuan.com/4556.html有點(diǎn)復(fù)雜,看不太懂
  • https://kernel.taobao.org/2019/06/io_uring-a-new-linux-asynchronous-io-API/最新的io_uring
  • https://zhuanlan.zhihu.com/p/149836046一開始linux AIO的設(shè)計(jì)出發(fā)點(diǎn)和io_uring,有點(diǎn)復(fù)雜比如阻塞點(diǎn)
  • understanding linux kernel的6.2章節(jié)
  • 總結(jié)

    以上是生活随笔為你收集整理的异步IO实现和应用场景的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。