DPDK 入門
DPDK旁路原理

原來內核協議棧的方式數據是從 網卡-->驅動-->協議棧-->socket接口-->業務
而DPDK的方式是基於UIO(Userspace I/O)旁路數據。數據從 網卡-->DPDK輪詢模式-->DPDK基礎庫-->業務
DPDK的基石UIO
為了讓驅動運行在用戶態,linux提供UIO機制,使用UIO可以通過read感知中斷,通過mmap實現核網卡的通訊
UIO原理

要開發用戶態驅動有幾個步驟:
-
開發運行在內核的UIO模塊,因為硬中斷只能在內核處理
-
通過/dev/uioX讀取中斷
-
通過mmap和外設共享內存
DKDP核心優化
DPDK的UIO驅動屏蔽了硬件發出的中斷,然后在用戶態采用主動輪訓的方式,這種模式被稱為PMD(Poll Mode Driver)
UIO 旁路了內核,主動輪訓去掉硬中斷,DPDK從而可以在用戶態做收發包處理。帶來zero copy,無系統調用的好處,同步處理減少上下文切換帶來的Cache MIss。
運行在PMD的CORE會處於CPU100%的狀態。
網絡空閑時CPU 長期空轉,會帶來能耗問題。所以,DPDK推出interrupt DPDK模式。
interrupt DPDK:

DPDK的高性能代碼實現
1. 采用HugePage減少TLB Miss
默認下Linux采用4KB為一頁,頁越小內存越大,頁表的開銷越大,頁表的內存占用也越大。CPU有TLB(Translation Lookaside Buffer)成本高所以一般就只能存放幾百到上千個頁表項。如果進程要使用64G內存,則64G/4KB=16000000(一千六百萬)頁,每頁在頁表項中占用16000000 * 4B=62MB。如果用HugePage采用2MB作為一頁,只需64G/2MB=2000,數量不在同個級別。
而DPDK采用HugePage,在x86-64下支持2MB、1GB的頁大小,幾何級的降低了頁表項的大小,從而減少TLB-Miss。並提供了內存池(Mempool)、MBuf、無鎖環(Ring)、Bitmap等基礎庫。根據我們的實踐,在數據平面(Data Plane)頻繁的內存分配釋放,必須使用內存池,不能直接使用rte_malloc,DPDK的內存分配實現非常簡陋,不如ptmalloc。
2. SNA(Shared-nothing Architecture)
軟件架構去中心化,盡量避免全局共享,帶來全局競爭,失去橫向擴展的能力。NUMA體系下不跨Node遠程使用內存。
3. SIMD(Single Instruction Multiple Data)
從最早的mmx/sse到最新的avx2,SIMD的能力一直在增強。DPDK采用批量同時處理多個包,再用向量編程,一個周期內對所有包進行處理。比如,memcpy就使用SIMD來提高速度。
SIMD在游戲后台比較常見,但是其他業務如果有類似批量處理的場景,要提高性能,也可看看能否滿足。
4. 不使用慢速API
這里需要重新定義一下慢速API,比如說gettimeofday,雖然在64位下通過vDSO已經不需要陷入內核態,只是一個純內存訪問,每秒也能達到幾千萬的級別。但是,不要忘記了我們在10GE下,每秒的處理能力就要達到幾千萬。所以即使是gettimeofday也屬於慢速API。DPDK提供Cycles接口,例如rte_get_tsc_cycles接口,基於HPET或TSC實現。
