io_uring只適用於存儲IO?大錯特錯

2020-10-19 IT小白進階之路

傳統高性能網絡編程通常是基於select, epoll, kequeue等機制實現,網絡上有非常多的資料介紹基於這幾種接口的編程模型,尤其是epoll,nginx, redis等都基於其構建,穩定高效,但隨著linux kernel主線在v5.1版本引入io_uring新異步編程框架,在高並發網絡編程方面我們多了一個利器。

1. 概述

傳統高性能網絡編程通常是基於select, epoll, kequeue等機制實現,網絡上有非常多的資料介紹基於這幾種接口的編程模型,尤其是epoll,nginx, redis等都基於其構建,穩定高效,但隨著linux kernel主線在v5.1版本引入io_uring新異步編程框架,在高並發網絡編程方面我們多了一個利器。

io_uring在進行初始設計時就充分考慮其框架自身的高性能和通用性,不僅僅面向傳統基於塊設備的fs/io領域,對網絡異步編程也提供支持,其最終目的是實現linux下一切基於文件概念的異步編程。

2. echo_server場景下的性能對比

我們先看下io_uring和epoll在echo_server模型下的性能對比,測試環境為:

1. server端cpu Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz, client端cpu Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz

2. 兩臺物理機器,一臺做server, 一臺做client。

Note: 如下性能數據都是在meltdown和spectre漏洞修復場景下測試。

上圖是io_uring和epoll在echo_server場景下qps數據對比,可以看出在筆者的測試環境中,連接數1000及以上時,io_uring的性能優勢開始體現,io_uring的極限性能單core在24萬qps左右,而epoll單core只能達到20萬qps左右,收益在20%左右。

上圖統計的是io_uring和epoll在echo_server場景下系統調用上下文切換數量的對比,可以看出io_uring可以極大的減少用戶態到內核態的切換次數,在連接數超過300時,io_uring用戶態到內核態的切換次數基本可以忽略不計。

3. epoll 網絡編程模型

下面展開介紹epoll和io_uring兩種編程模型基本用法對比,首先介紹下傳統的epoll網絡編程模型, 通常採用如下模式:

struct epoll_event ev; /* for accept(2) */ ev.events = EPOLLIN; ev.data.fd = sock_listen_fd; epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_listen_fd, &ev); /* for recv(2) */ ev.events = EPOLLIN | EPOLLET; ev.data.fd = sock_conn_fd; epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_conn_fd, &ev); 然後在一個主循環中: new_events = epoll_wait(epollfd, events, MAX_EVENTS, -1); for (i = 0; i < new_events; ++i) { /* process every events */ ... }

本質上是實現類似如下事件驅動結構:

struct event { int fd; handler_t handler; };

將fd通過epoll_ctl進行註冊,當該fd上有事件ready, 在epoll_wait返回時可以獲知完成的事件,然後依次調用每個事件的handler, 每個handler裡調用recv(2), send(2)等進行消息收發。

4. io_uring 網絡編程模型

io_uring的網絡編程模型不同於epoll, 以recv(2)為例,它不需要通過epoll_ctl進行文件句柄的註冊,io_uring首先在用戶態用sqe結構描述一個io 請求,比如此處的recv(2)系統調用,然後就可以通過io_uring_enter(2)系統調用提交該recv(2)請求,用戶程序通過調用io_uring_submit_and_wait(3),類似於epoll_wait(2),獲得完成的io請求,cqe結構用於描述完成的ioq請求。

/* 用sqe對一次recv操作進行描述 */ struct io_uring_sqe *sqe = io_uring_get_sqe(ring); io_uring_prep_recv(sqe, fd, bufs[fd], size, 0); /* 提交該sqe, 也就是提交recv操作 */ io_uring_submit(&ring); /* 等待完成的事件 */ io_uring_submit_and_wait(&ring, 1); cqe_count = io_uring_peek_batch_cqe(&ring, cqes, sizeof(cqes) / sizeof(cqes[0])); for (i = 0; i < cqe_count; ++i) { struct io_uring_cqe *cqe = cqes[i]; /* 依次處理reap每一個io請求,然後可以調用請求對應的handler */ ... }

總結下:為什麼io_uring相比epoll模型能極大的減少用戶態到內核態的上下文切換?舉個簡單例子,epoll_wait返回1000個事件,則用戶態程序需要發起1000個系統調用,則就是1000個用戶態和內核態切換,而io_uring可以初始化1000個io請求的sqes, 然後調用一次io_uring_enter(2)系統調用就可以下發這1000個請求。

在meltdown和spectre漏洞沒有修復的場景下,io_uring相比於epoll的提升幾乎無,甚至略有下降,why? 我們不是減少了大量的用戶態到內核態的上下文切換?

原因是在meldown和spectre漏洞沒有修復的場景下,用戶態到內核態的切換開銷很小,所帶來的的收益不足以抵消io_uring框架自身的開銷,這也說明io_uirng框架本身需要進一步的優化。

詳細的epoll和io_uring基於echo_server模型的對比程序在 :https://github.com/OpenAnolis/io_uring-echo-server(詳見原文連結)。

5. 接下來的工作

1.目前從分析來看,io_uring框架本身存在的overhead不容小覷,需要進一步優化,我們已經在io_uring社區進行io_uring框架開銷不斷增大的討論,並已經開展了一系列的優化嘗試。

2.echo_server代表著一類編程模型,不是真實的應用,但redis, nginx等應用其實都是基於echo_server模型,將其用io_uirng來改造,理論上在cpu 漏洞修復場景下都會帶來明顯性能提升,我們已經在開展nginx, redis的io_uring適配工作,後續會有進一步的介紹。

https://www.linuxprobe.com/io-uring-storage.html

相關焦點

  • io_uring 新異步 IO 機制,性能提升超 150%,堪比 SPDK
    Alibaba Cloud Linux 2 LTS 版本率先提供了新異步 IO 機制 io_uring 的支持。io_uring 是由 block 維護者 Jens Axboe 開發的新異步 IO 框架。
  • 【翻譯】withoutboats的io-uring 筆記
    原文: Notes on io-uring地址: https://boats.gitlab.io/blog/post/io-uring/時間: 2020-05-06作者: Withoutboats (Saoirse Shipwreckt@Github)去年秋天,我正在開發一個庫,創建一套安全的API,實現在一個 io-uring
  • 使用Go進行io_uring的動手實踐
    int io_uring_setup(unsigned entries, struct io_uring_params *params);使用 liburing ,我們大致必須執行以下步驟:io_uring_queue_(init|exit)io_uring_get_sqeio_uring_prep_(readv|writev|other)io_uring_sqe_set_dataio_uring
  • 下一代異步 IO 技術解密
    上一篇我們在 Alibaba Cloud Linux 2 上對比測試了 io_uring 與 libaio 以及 SPDK,可以看到 io_uring 帶來的性能提升非常明顯。這篇文章我們詳細分析下 io_uring 的原理,以及我們在 io_uring 社區所做的工作。
  • 技術貼:可實現RSSD雲硬碟120萬IOPS的SPDK IO路徑優化實踐
    簡介用戶對超高並發、超大規模計算等需求推動了存儲硬體技術的不斷發展,存儲集群的性能越來越好,延時也越來越低,對整體IO路徑的性能要求也越來越高。主要原因是使用了vhost之後qemu只控制了設備的控制鏈路,而設備的數據鏈路已經託管給了後端的SPDK,也就是說qemu沒有設備的數據流IO路徑所以並不知道一個設備那些部分被寫入了。在考察了現有的qemu在線遷移功能後,我們覺著這個技術難點並不是不能解決的,因此我們決定在qemu裡開發一套針對vhost存儲設備的在線遷移功能。
  • 混合存儲陣列會給Fusion-io至少5年
    DOSTOR存儲在線 4月27日原創報導: Fusion-io對NexGen公司的收購如果放在兩年前,會被新聞媒體和圈裡人當作笑話。2、收購NexGen能夠讓Fusion-io獲得一些新的客戶群和附加的收入,一方面,Fusion-io成為中小企業的混合快閃記憶體/磁碟陣列供應商,中小企業也需要高性能的存儲系統,他們也希望有「具有快閃記憶體性能的存儲陣列「,但可負擔成本成了絆腳石,Fusion-io加上NexGen的實力,相信應該可以滿足他們的需求。
  • 阿里雲 E-MapReduce 全面支持 Alluxio
    這層抽象之上的計算只需要和Alluxio交互來訪問數據;而這層抽象之下可以同時對接多個不同的持久化存儲(比如一個OSS加上一個HDFS部署),而這層抽象本身又是由部署在靠近計算的內存級Alluxio存儲系統來實現。
  • IO知識點學習
    2 字節流2.1 一切皆為字節一切數據在存儲時抽象類是表示字節輸入流的所有類的超類,可以讀取字節信息到內存,定義了字節輸入流的基本共性方法public void close():關閉此輸入流並釋放資源public abstract int read ():從輸入流讀取數據的下一個字節public int read(byte[] b):從輸入流中讀取一些字節數,並將它們存儲到字節數組中
  • 如何讓linux伺服器磁碟io性能翻倍
    最小分配當文件擴大,需要分配磁碟空間時,大部分文件系統不會僅僅只分配當前需要的磁碟空間,而是會多分配一些磁碟空間。這樣下次文件擴大時就可以使用已經分配好的空間,而不會頻繁的去分配新空間。例如ext3下,每次分配磁碟空間時,最小是分配8KB。
  • 現代存儲性能「過剩」,API成最大瓶頸
    作為從業者,我有幸看到存儲技術的迅速發展,工作中的實際感受更像是做團隊動員。今年,我換了份工作,加入了一家擁有眾多從業背景不同的工程師的大型企業。特別讓我驚訝的是,雖然這些同事也非常聰明睿智,但大部分都對如何充分運用現代存儲技術的性能優勢存在誤解。換句話說,他們知道存儲技術在不斷改進,但卻不清楚究竟是怎麼個改進法。
  • hole.io怎麼玩 hole.io玩法攻略介紹
    導 讀 hole.io怎麼玩?
  • IO,對象傳輸的基石(二)
    ;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;//對象流 ObjectInputpublic class Test { public static void main(String[]
  • 從開源到商業,Alluxio 是怎麼做的?
    Alluxio,原名Tachyon,在早些時候獲得了矽谷風投Andreessen Horowitz 750萬美元的A輪投資。
  • Gate.io 跨所禮遇一整月:他所VIP免費領Wallet.io S1、iPhone 12...
    1.如果小明在Gate.io無GT持倉,則根據30天交易量,小明可在Gate.io申請VIP 5;2.如果小明在Gate.io有1000 GT持倉,但未達到升級VIP 6所需的最低持倉量,小明可在Gate.io申請VIP 5;3.如果小明的GT持倉有2000 GT,滿足Gate.io VIP 6所需最低GT持倉量,小明可在Gate.io申請VIP 6。
  • AWS宣布Amazon EBS io2卷的全面上市
    (AWS)宣布io2的全面可用性,io2是適用於Amazon Elastic Block Store(Amazon EBS)的下一代Provisioned IOPS SSD卷。與io1 Amazon EBS卷提供的99.9%的耐久性相比,新的io2卷的設計具有100倍的高卷耐久性(99.999%)。更高的卷持久性減少了存儲故障的可能性,並使客戶數據的主副本更具彈性,從而提高了應用程式可用性。
  • 諸葛io產品VP於曉松談諸葛io的產品方法論
    DoNews 9月27日消息(記者 趙晉傑)關注數據驅動增長的公司越來越多,諸葛io這家專注做大數據分析服務的公司就是其中發展迅猛的代表之一,其提供的產品解決方案也被認為是新一代的數字營銷方案。DoNews得到內部消息,諸葛io剛又獲得一筆新的融資。近日,DoNews約諸葛io產品VP於曉松就諸葛io的發展談了談他獨特的產品方法論。
  • Flask-SocketIO 簡單使用指南
    也可以使用基於 Werkzeug 的 Flask 開發伺服器,但需要注意的是,它缺乏其他兩個選項的性能,因此它只應用於簡單的開發環境。此選項僅支持長輪詢傳輸。擴展會根據安裝的內容自動檢測要使用的異步框架。優先考慮 eventlet,然後是 gevent。對於 gevent 中的WebSocket 支持,首選 uWSGI,然後是 gevent-websocket。
  • IO,對象傳輸的基石(一)
    ;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.io.Writer; //用緩衝流和緩衝數組提高讀寫效率
  • Swipe.io超45萬易主,一個被低估的域名後綴.io!
    近日,Swipe.io在park.io上交易成功,價格高達45萬元,這也是截止目前為止.io後綴交易金額最高的域名。該域名於2012年註冊,直譯為「猛擊、偷竊、刷卡、滑動」等。對應諸多國外終端公司,例如,誕生於1962年的美國休斯敦清潔品牌;歐盟國家的電子商務以及支付框架開發商;巴西的區塊鏈網絡公司等等。
  • JAVA IO Stream流總結
    Java中I/O操作主要是指使用 java.io 包下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫 出數據。一.java.io.File 類1.File類中常用的方法:創建:l createNewFile() 在指定位置創建一個空文件,成功就返回true,如果已存在就不創建然後返回falsel mkdir() 在指定位置創建目錄,這只會創建最後一級目錄,如果上級目錄不存在就拋異常。l mkdirs() 在指定位置創建目錄,這會創建路徑中所有不存在的目錄。