五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

epoll與io_uring服務(wù)器編程實踐及對比

2023-02-28 14:45 作者:linux技術(shù)棧  | 我要投稿

項目地址:TinyWebServer-with-liburing(github.com)

epoll原理及API使用方式

epoll是一種IO多路復(fù)用的機(jī)制,一般搭配非阻塞IO實現(xiàn),是一種同步IO。工作邏輯上體現(xiàn)為向一個epoll實例注冊一批需要監(jiān)聽的套接字和期望獲得通知的事件,然后等待內(nèi)核對到來的事件進(jìn)行通知,通過收割到來的不同事件來執(zhí)行具體的操作。

系統(tǒng)提供了三個API以供使用,分別是(以下來自庫頭文件):

以TinyWebServer為藍(lán)本,在實際的服務(wù)器編程中,需要對epoll_ctl函數(shù)進(jìn)行封裝,將需要監(jiān)聽的事件提前設(shè)定好,例如以下函數(shù):

如果需要刪除一個描述符,封裝的函數(shù)類似:

正式開始工作前,先是使用epoll_create函數(shù)創(chuàng)建一個epoll實例,然后使用封裝的函數(shù)對需要監(jiān)聽的文件描述符添加到實例中,然后在一個事件循環(huán)中不斷調(diào)用epoll_wait函數(shù)對到來的事件進(jìn)行收割和處理,例如:

io_uring原理及l(fā)iburing庫使用方式

io_uring是linux于2019年引入內(nèi)核的異步IO,支持普通的任務(wù)提交模式和輪詢模式,用戶向其一次性提交多個需要完成的系統(tǒng)調(diào)用任務(wù),然后內(nèi)核會對任務(wù)進(jìn)行收割并返回任務(wù)完成的結(jié)果,用戶只需獲取任務(wù)完成的結(jié)果并進(jìn)行相應(yīng)的處理,而無需一直等待系統(tǒng)調(diào)用的完成。

在實際交互上,用戶和內(nèi)核將在內(nèi)存中共享一塊環(huán)形隊列,用戶需要提交的任務(wù)和收割完成的任務(wù)都是在這一區(qū)域中進(jìn)行,內(nèi)核亦然,然后用戶根據(jù)設(shè)置時的選項決定是否使用系統(tǒng)調(diào)用提交和收割任務(wù),這就避免了內(nèi)核態(tài)和用戶態(tài)之間的數(shù)據(jù)拷貝,降低了開銷。

部分縮寫:complete queue(cq)、submission queue(sq)和submission queue entries(sqes)。sq中儲存的是對sqe中的索引指針,由io_uring_sqe結(jié)構(gòu)描述;cq中儲存的是完成的隊列項,由io_uring_cqe結(jié)構(gòu)描述。

系統(tǒng)提供了三個系統(tǒng)調(diào)用以供使用,以下將用liburing庫的源碼和io_uring的man page進(jìn)行分析:


用戶態(tài)在使用前需要先使用io_uring_setup初始化一個實例,然后對sqring、cqring和sqes三塊區(qū)域進(jìn)行內(nèi)存映射,并自行維護(hù)用戶態(tài)的sq/cq數(shù)據(jù)結(jié)構(gòu),總體操作流程較為復(fù)雜,而liburing中提供了一系列的封裝函數(shù)可以直接使用:


在完成了以上步驟后,還需要對期望提交的系統(tǒng)調(diào)用進(jìn)行進(jìn)一步的封裝,基本流程為先獲取一個空閑的sqe指針,然后填充其中的opcode、fd、off、user_data等必要信息,其數(shù)據(jù)結(jié)構(gòu)如下:

liburing提供了多個函數(shù)對以上流程進(jìn)行操作,以io_uring-echo-server為藍(lán)本,一次任務(wù)提交的操作如下:

在設(shè)置完需要進(jìn)行的任務(wù)后,則需要根據(jù)設(shè)置時的選項對任務(wù)進(jìn)行提交和收割,如果設(shè)置時的選項是IORING_SETUP_IOPOLL,則需要通過io_uring_enter對任務(wù)進(jìn)行提交和收割;如果是IORING_SETUP_SQPOLL,則只需等待并對完成隊列進(jìn)行收割;如果都沒設(shè)置,則只需要通過io_uring_enter對任務(wù)進(jìn)行提交并手動收割任務(wù)。提交任務(wù)時,用戶將提交的任務(wù)sqe放置到sq_ring的尾部,內(nèi)核從頭部獲取提交的任務(wù);完成任務(wù)時,內(nèi)核將完成的cqe放置到cq_ring的尾部,用戶從頭部收割已完成的任務(wù)。實際使用中這些步驟會更加復(fù)雜,因為用戶需自行調(diào)整其用戶態(tài)數(shù)據(jù)結(jié)構(gòu)的頭尾指針。在liburing中提供了提交和收割的封裝函數(shù):


負(fù)責(zé)收割完成任務(wù)的函數(shù)將返回完成的個數(shù),并填充用戶自行創(chuàng)建的cqe數(shù)組:

以TinyWebServer-with-liburing為藍(lán)本,完成準(zhǔn)備工作后,在進(jìn)入具體事件循環(huán)前需要先行提交一個對監(jiān)聽套接字的accept任務(wù),然后不斷阻塞等待任務(wù)完成、收割任務(wù)然后根據(jù)返回的任務(wù)狀態(tài)進(jìn)行下一步處理后提交新的任務(wù):


io_uring_register在liburing的封裝接口代碼如下:

該系統(tǒng)調(diào)用通過注冊文件或用戶緩沖區(qū),內(nèi)核可以對內(nèi)部數(shù)據(jù)結(jié)構(gòu)進(jìn)行長期引用,或創(chuàng)建對應(yīng)用程序內(nèi)存的長期映射,從而大大減少I/O開銷。但其在網(wǎng)絡(luò)編程領(lǐng)域似乎不太完善(也可能是個人水平原因),暫此按下不表,關(guān)于該系統(tǒng)調(diào)用的更多信息可以查閱官方文檔。

系統(tǒng)調(diào)用開銷對比

系統(tǒng)調(diào)用的開銷

現(xiàn)代操作系統(tǒng)由于支持CPU級別的SYSCALL/SYSENTER指令,所以相較于過去開銷巨大的INT指令而言系統(tǒng)調(diào)用的開銷已經(jīng)被盡可能的減少;但是和普通的函數(shù)調(diào)用相比,系統(tǒng)調(diào)用在CPU上下文、棧幀切換、TLB刷新等方面依然有著一定的成本。

傳統(tǒng)INT軟中斷系統(tǒng)調(diào)用

在用戶態(tài),用戶通過查閱系統(tǒng)調(diào)用編號表并將不同的值放入寄存器中來觸發(fā)一個軟中斷;

而在內(nèi)核態(tài),內(nèi)核在收到中斷后將調(diào)用事先注冊的系統(tǒng)調(diào)用回調(diào)函數(shù)對參數(shù)進(jìn)行處理,而后執(zhí)行中斷處理器?entry_INT80_32?處理系統(tǒng)調(diào)用,將寄存器的值儲存到內(nèi)核棧上,然后檢查系統(tǒng)調(diào)用的序號是否合法并系統(tǒng)調(diào)用表中查找對應(yīng)的系統(tǒng)調(diào)用實現(xiàn)和傳入寄存器值,在運(yùn)行期間會在用戶態(tài)和內(nèi)核態(tài)內(nèi)存直接傳輸數(shù)據(jù),在退出時調(diào)用iret指令從棧上彈出先前保存的用戶態(tài)地址和寄存器值。如果涉及到堆棧切換的話CPU的執(zhí)行流程會更長。

現(xiàn)代syscall/sysret指令

該指令總體流程與INT軟中斷類似,內(nèi)核會在初始化時將相應(yīng)的回調(diào)函數(shù)地址寫到MSR寄存器中,并且遵循調(diào)用約定(convention),用戶空間程序?qū)⑾到y(tǒng)調(diào)用編號放到rax寄存器而參數(shù)放到通用寄存器,而后會通過同樣的查表方式進(jìn)入內(nèi)核。內(nèi)核在返回時調(diào)用sysret指令將執(zhí)行過程返還給用戶程序。兩條指令在執(zhí)行時便運(yùn)行在最高權(quán)限級別,而且不必觸發(fā)軟中斷。

普通的函數(shù)調(diào)用

基本通過call/jmp指令進(jìn)行,call指令在CPU層面要做的只有壓棧、出棧、加載、執(zhí)行、返回、判斷幾件事,顯然要比系統(tǒng)調(diào)用指令的開銷要小得多。

系統(tǒng)調(diào)用數(shù)量對比

對比設(shè)置:服務(wù)器軟件為TinyWebServer(epoll)和TinyWebServer-with-liburing(io_uring),兩者均關(guān)閉日志,epoll開啟雙ET選項,使用strace和perf進(jìn)行跟蹤記錄,使用webbench以相同參數(shù)進(jìn)行測試。在測試過程中,需要使用sudo提權(quán)執(zhí)行perf才能在io_uring收集到足夠的樣本和調(diào)用棧信息,epoll則不需要。

io_uring

epoll

從火焰圖可以看出,epoll花費(fèi)了大量操作在執(zhí)行readv和writev兩個系統(tǒng)調(diào)用上,而accept、epoll_wait、epoll_ctl等系統(tǒng)調(diào)用所執(zhí)行的次數(shù)則少了很多;

而io_uring方面大部分的操作都是內(nèi)核在執(zhí)行,用戶態(tài)所需要做的只是提交所需執(zhí)行的任務(wù),且一次可以提交多個。

strace返回的結(jié)果是,一次對訪問epoll的網(wǎng)頁訪問需要經(jīng)歷epoll_wait-epoll_ctl-readv-writev多個系統(tǒng)調(diào)用,而io_uring只需要經(jīng)過io_uring_enter和io_register(初次訪問)兩個系統(tǒng)調(diào)用,在高并發(fā)場景下對系統(tǒng)調(diào)用的減少是巨大的。

實際性能對比

測試環(huán)境:wsl2,內(nèi)核版本5.10.60.1,發(fā)行版為Debian

硬件:I5-9400,16gDDR4

使用webbench進(jìn)行簡易測試,模擬10500、30500臺客戶端,持續(xù)時間為5s,分別在正常訪問和不等待返回兩種模式下進(jìn)行測試,兩個客戶端均關(guān)閉日志記錄,epoll開啟雙ET模式,比較每分鐘發(fā)送頁面數(shù),結(jié)果如下:

可見,雖然該服務(wù)器還有著一些問題,但使用io_uring在高并發(fā)的場景下相對epoll仍然有著巨大的性能優(yōu)勢。

已知問題

關(guān)閉服務(wù)器中的io_uring_register相關(guān)功能會解決壓力測試下出現(xiàn)大量failed的問題,但也會導(dǎo)致性能斷崖式下跌,同樣測試條件下只有開啟該功能的50%左右的性能;

在源碼中開啟該調(diào)用的功能對IO性能的提升是顯著的,但會導(dǎo)致被注冊的文件描述符無法被關(guān)閉,長期處于close_wait狀態(tài),導(dǎo)致系統(tǒng)資源被大量占用;

accept系統(tǒng)調(diào)用似乎不支持polling模式,當(dāng)在設(shè)置iouring時開啟了IQ或是SQ模式時都會返回invalid argument的錯誤;

在部分系統(tǒng)例如WSL2上需要使用sudo提權(quán)才能啟用更大的隊列深度。


作者:greatmfc
鏈接:
https://juejin.cn/post/7074212680071905311


(服務(wù)器開發(fā))磁盤io的主流:io_uring是什么?比epoll更強(qiáng)?會成為未來io的主流嗎?

LinuxC/C++后臺服務(wù)器開發(fā)/架構(gòu)師面試題、學(xué)習(xí)資料、教學(xué)視頻和學(xué)習(xí)路線圖(資料包括C/C++,Linux,golang技術(shù),Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協(xié)程,DPDK,ffmpeg等),免費(fèi)分享有需要的可以自行添加學(xué)習(xí)交流 群739729163 領(lǐng)取

epoll與io_uring服務(wù)器編程實踐及對比的評論 (共 條)

分享到微博請遵守國家法律
景洪市| 华宁县| 阿巴嘎旗| 翁牛特旗| 延川县| 西昌市| 诏安县| 晴隆县| 隆回县| 辉县市| 突泉县| 灌阳县| 肇源县| 股票| 郁南县| 南安市| 织金县| 龙胜| 武宁县| 南昌县| 宣恩县| 两当县| 上杭县| 太谷县| 桃江县| 政和县| 商城县| 河津市| 罗甸县| 九寨沟县| 肃北| 巨鹿县| 荆州市| 杨浦区| 镇坪县| 彭州市| 沁阳市| 门头沟区| 浑源县| 凌源市| 广西|