简单的DPDK介绍与分析
DPDK介紹及分析
什么是DPDK
Intel? DPDK 全稱 __Intel Data Plane Development Kit__,是intel提供的數據平面開發工具集,為Intel architecture(IA)處理器架構下用戶空間高效的數據包處理提供庫函數和驅動的支持,它不同于Linux系統以通用性設計為目的,而是專注于網絡應用中數據包的高性能處理。其工作在用戶層,取代傳統Linux系統中的網絡數據報文處理。但需要注意的是,DPDK提供的是高性能處理報文的能力,而不是對報文的處理。這也提供了我們自定義用戶協議棧的能力。
因此,任何基于DPDK的應用開發都需要自建協議棧,或者使用基于DPDK的協議棧。目前比較有名的基于DPDK的協議棧有MTCP,DPDK-ANS等。這里不作討論。DPDK的優勢
使用linux下的AB發送POST請求壓測基于DPDK(MTCP)的lightppd服務器和基于Linux的lightppd服務器。不同大小的數據結果如上所示。DPDK的吞吐達到了Linux的2倍。值得一提的是,CPU的消耗具有迷惑性,后面會提到DPDK采用輪詢的方式,我們的機器上有24個邏輯核,我分配了2個核給DPDK獨占。也就是說,并不能認為DPDK消耗的CPU是基于Linux的2倍。__事實上,無論數據多少,DPDK在我們的測試環境下只會占用8%左右的CPU。__
C10K Problem
It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now. —— Dan KegelC10K 問題狹義的說,就是如何同時承載1W+的客戶。從per client per thread 到 many client per thread,從阻塞式IO到IO復用,異步IO,從輪詢事件模型到變更通知模型。這個問題就目前來看,似乎已經不再是一個障礙。但是考慮一下,C100K,C1M問題呢?似乎問題可以繼續擴展下去。C10K問題的關鍵在于盡可能減少CPU等核心計算資源消耗,充分地利用服務器的資源。這些擴展問題,也可以在這些方面思考。但是epoll異步模型真的還適合C100K,C1M問題嗎?
數據處理流程
以Linux為例,傳統網絡設備驅動包處理的過程如下:
- 數據包到達網卡設備
- 網卡設備依據配置進行DMA操作
- 網卡發送中斷,喚醒處理器
- 驅動軟件填充讀寫緩沖區數據結構
- 內核協議棧中處理數據包
- 通知用戶層取包
- 數據到達邏輯層和業務層,進行處理
linux很明顯設計的是通用的網絡處理。但是,海量數據下中斷是否真的有效嗎?我們真的需要所有的協議棧嗎?內核態用戶態的內存拷貝是否可以避免,epoll模型是否有更好的替代?
中斷 V.s 輪詢
隨著網絡接口帶寬從千兆到萬兆,每一個報文都會觸發一次中斷的開銷是巨大的。NAPI機制是一種解決這個問題的方法之一,它的核心概念就是不采用中斷的方式讀取數據,而代之以首先采用中斷喚醒數據接收的服務程序,然后在使用輪詢的方式一次性處理多個數據,直到網卡接收隊列為空才繼續打開中斷。DAPI有一個極大的缺陷,它只適合大量的小數據,在數據大小過大時(即使使用DMA),會退化成中斷模式。
DPDK 則使用純輪詢模式去解決這個問題,收發包不使用任何中斷,但這不意味著DPDK不支持中斷,畢竟實際應用中,存在網絡的潮汐效應,低潮期輪詢勢必產生內核空轉。因此DPDK同時也支持類似NAPI的機制,用戶可以配置何時關閉中斷,何時輪詢結束等等。例如,在2張網卡的機器上,一般推薦,DPDK獨占4個邏輯核。如果這不能接受,就可以考慮混合中斷輪詢的機制。
用戶態驅動
Linux 中傳統的 I/O 操作是一種緩沖 I/O,I/O 過程中產生的數據傳輸通常需要在用戶態和內核態之間進行多次的拷貝操作。在某些情況下,這些數據拷貝操作會極大地降低數據傳輸的性能。應運而生的是一種叫做零拷貝的技術,采用直接IO,mmap/sendfile,寫時復制等一系列策略,盡量避免 CPU 將數據從一塊存儲拷貝到另外一塊存儲,篇幅有限,這里不做過多闡述。
我們注意到,盡管DPDK實現的是Linux內核的功能,但是DPDK依舊是工作在用戶態中的。應用數據通過DPDK傳輸是完全可以避免相互拷貝的。DPDK的包全部在用戶空間,使用mbuf內存池管理。DPDK空間與應用層空間的內存交換不需要拷貝,只需要做控制權轉移。
多核編程與無鎖
多線程編程早已不是什么新鮮的事物了,多線程的初衷是提高整體應用程序的性能,但是如果不加注意,就會將多線程的創建和銷毀開銷,鎖競爭,訪存沖突,cache失效,上下文切換等諸多消耗性能的因素引入進來。這也是Ngnix使用單線程模型能獲得比Apache多線程下性能更高的原因之一。
為了進一步提高性能,就必須仔細考慮線程在CPU不同核上的分布情況,這也就是常說的多核編程。多核編程和多線程有很大的不同:多線程是指每個CPU上可以運行多個線程,涉及到線程調度、鎖機制以及上下文的切換;而多核則是每個CPU核一個線程,核心之間訪問數據無需上鎖。為了最大限度減少線程調度的資源消耗,需要將Linux綁定在特定的核上,釋放其余核心來專供應用程序使用。DPDK就是采用的這種方式,不過因為DPDK工作在應用層中,即使設置了CPU親和性,操作系統還是會對這些核進行調度。因此,DPDK推薦通過設置孤立核的方式來進一步減少競爭。同時還需要考慮CPU特性和系統是否支持NUMA架構,如果支持的話,不同插槽上CPU的進程要避免訪問遠端內存,盡量訪問本端內存。這里不做過多描述
無鎖編程,不管是之前提及的多核編程還是多線程編程,只要涉及到多個執行單元共享同一快數據的情況,一般都會需要同步技術。嚴格地說,無鎖編程本質上是一種非阻塞性同步技術,所謂無鎖,顧名思義,就是不需要用鎖,使得所有操作表現出原子的語義。無鎖一般來說,被人推崇的是其高于鎖編程的效率,這里不過多贅述了。但是考慮一下,無鎖真的無論如何都比鎖編程效率高嗎?有沒有什么極端的例子呢。
訪存開銷(CaCHE & TLB)
我們知道內存的訪問速度遠遠不如Cache的訪問和CPU的頻率的。當我們定義了一個數據結構或內存后,在內存中就有一個地址和其相對應,對于讀,首先從內存中讀入到Cache,最后送到寄存器中;對于寫,則從寄存器寫回Cache,最后通過總線寫回內存。這份內存可能對應多個處理器中的Cache。任何一個處理器對該Cache的寫,都會使得其他處理器Cache不一致,導致一次寫回和Cache Miss。因此,DPDK在設計上,盡量避免多個核訪問同一個內存地址,盡量避免共享導致的Cache不一致問題。(Cache不一致的本質是CPU獨占CAHCE)
其次我們知道Cache是按照Cache line來構成的。即使我們給每個核分配各自獨立的數據結構(常見的: struct Data datas[NUM_CORE];)。如果我們的 數據結構不是以Cache line對齊的,還是會導致一致性問題。因此,DPDK在定義多核各自的備份時,都是按照Cache line對齊的。
對于TLB,DPDK要求使用大頁內存來減少TLB Miss,這可以適用任何程序。倒算不上DPDK的優化。TLB類似Cache,存放的是頁表項。以4K內存頁為例,應用程序需要使用2M的內存則需要使用512個內容頁,也就是512個TLB表項。如果是2M內存頁,則只需要1個TLB表項。
硬件加速
DPDK 畢竟是Intel?自己的產品總是可以在第一時間利用到Intel?硬件的優化。這也是在一些類似的產品中,DPDK最大的優勢。
Intel? DDIO技術。它的核心在于,使網卡跟第三級Cache直接交換數據,繞過低速的內存交換。
硬件卸載功能,它是指將軟件的某些功能下移到硬件實現。不同的硬件支持的功能也略有不同,在硬件支持的情況下,DPDK提供大致上有WLAN,校驗和計算,TCP 分片,TCP收包聚合等等。
DPDK 轉發模型
run2Completion 模型
我們在多核編程和流分類章節提到過,DPDK 傾向于單核單線程獨占,每個線程對應一條網卡隊列,這樣可以極大的解決同步問題和Cache不一致,負載均衡問題。像這樣,每個報文的生命周期都只會出現在其中的一個線程上,我們稱為run2completion模型。這個模型有很高的擴展性,在上層業務邏輯很簡單的情況下(比如,3層轉發,DNS服務器),有很高的性能,然而一旦業務邏輯變得復雜,將存在處理流程上的依賴問題。其次這個模型,在調用DPDK的API上需要二次開發,最重要的,考慮到網卡隊列數量的限制,能夠利用的邏輯核不多。(在我們的機器上,2張網卡,每個網卡最多8條隊列,那么我們最多只能利用16個邏輯核。在我們24邏輯核的機器上,有8個核無法使用。(BTW,實驗數據告訴我們,網卡隊列為2-4時,性能最好)針對這個問題,DPDK也支持流水線模型(Pipe Line)。
Pipe Line模型
Pipe Line模型主要思想是將不同的工作交給不同的模塊,每一個模塊只處理特定的事務。每個模塊都有輸入輸出,通過這些輸入輸出將這些模塊連接起來。特別的,這些模塊可以位于同一個邏輯核上,也可以處于不同的邏輯核上,這依賴不同的業務實現邏輯了。這樣,我們基于DPDK可以實現更復雜的業務邏輯。但盡管不同的邏輯核之間使用無鎖隊列來交換數據,多核之間依然存在Cache一致性的問題。但是相對的,這個模型可以充分利用物理機器的計算資源。
簡而言之,Run2Completion模型適合業務邏輯簡單的業務,Pipe Line模型適合業務邏輯復雜的業務。具體采用何種模型需要看具體情況。
其他優化技術
-
內存預讀
我們這里主要是指軟件的預讀,通過使用匯編指令,在性能軟件相關區域,把即將用到的數據提前從內存直接讀取到Cache中,減少處理器等待的時間。DPDK在很多核心性能區域使用了這個技術。但Cache本身是有限的,我們在基于DPDK開發時,不能濫用這個指令,Cache過重反而有可能會降低性能,在實際開發中,需要不斷權衡,充分測試。DPDK將這些匯編指令簡單了做了封裝,有興趣可以參看DPDK源碼。 -
分支預測
這個倒算不上什么稀罕技術,是一個比較普及的編程手段了。這個主要使用在頻繁的條件轉移上,一般情況下,處理器有50%的幾率預測失敗。在Tnet中就大量使用了這種技術來提高性能。不了解的同學可以看看http://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array提出的這個問題,基本可以有一個簡單了解,這里不深入提及。 - 充分利用CPU亂序執行能力
DPDK實踐
- download dpdk.tar (如果是在虛擬機中開發,請按照http://dpdk.org/dev/patchwork/patch/945/ 中手動修復一個BUG)
- make config T=x86_64-native-linuxapp-gcc (require kernel-devel 。需要注意的是,請使用uname -r 查看系統版本。 保證yum 安裝的版本跟內核版本一致,如果不一致請記得指定版本)
- 動態加載驅動 modprobe uio ;cd kmod & insmod igb_uio.ko ; (卸載 rmmod , 重載 remod)
- 設置hugepage (稍微設置大一些,其中超過1G的大頁無法在開機后配置,請在linxu 啟動腳本修改)。
- 卸載系統網卡驅動,綁定DPDK驅動 1.ifconfig xxx down 2.cd tool & ./dbdk-devbind --bind=igb_uio xxx 如果成功,再次使用 ifconfig 就看不到那個網卡了。注意,DPDK只會使用綁定DPDK驅動的網卡,不會影響其他未綁定網卡的處理流程。
- run testcase
總結
以上是生活随笔為你收集整理的简单的DPDK介绍与分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WKWebView中经常用到的操作
- 下一篇: EE4J项目情况汇总,微软加入Jakar