www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > CPP開發(fā)者
[導(dǎo)讀]↓推薦關(guān)注↓hi,大家好,由于移動(dòng)互聯(lián)網(wǎng)不斷發(fā)展,導(dǎo)致網(wǎng)絡(luò)流量徒增,推動(dòng)著網(wǎng)絡(luò)技術(shù)不斷地發(fā)展,而CPU的運(yùn)行頻率基本停留在10年前的水平,為了迎接超高速網(wǎng)絡(luò)技術(shù)的挑戰(zhàn),軟件也需要大幅度創(chuàng)新,結(jié)合硬件技術(shù)的發(fā)展,DPDK(DataPlaneDevelopmentKit),一個(gè)以軟件...

推薦關(guān)注↓

hi,大家好,由于移動(dòng)互聯(lián)網(wǎng)不斷發(fā)展,導(dǎo)致網(wǎng)絡(luò)流量徒增,推動(dòng)著網(wǎng)絡(luò)技術(shù)不斷地發(fā)展,而CPU的運(yùn)行頻率基本停留在10年前的水平,為了迎接超高速網(wǎng)絡(luò)技術(shù)的挑戰(zhàn),軟件也需要大幅度創(chuàng)新,結(jié)合硬件技術(shù)的發(fā)展,DPDK(Data Plane Development Kit),一個(gè)以軟件優(yōu)化為主的數(shù)據(jù)面技術(shù)應(yīng)時(shí)而生,它為今天NFV技術(shù)的發(fā)展提供了絕佳的平臺(tái)可行性。


NFV:Network functions virtualization,網(wǎng)絡(luò)功能虛擬化。


同時(shí)作為技術(shù)人員,我們可以從中DPDK學(xué)習(xí)大量的高性能編程技巧和代碼優(yōu)化技巧,包括高性能軟件架構(gòu)最佳實(shí)踐、高效數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)內(nèi)存優(yōu)化技巧、應(yīng)用程序性能分析以及網(wǎng)絡(luò)性能優(yōu)化的技巧

一、網(wǎng)絡(luò)IO的處境和趨勢(shì)

從我們用戶的使用就可以感受到網(wǎng)速一直在提升,而網(wǎng)絡(luò)技術(shù)的發(fā)展也從1GE/10GE/25GE/40GE/100GE的演變,從中可以得出單機(jī)的網(wǎng)絡(luò)IO能力必須跟上時(shí)代的發(fā)展。



1.?傳統(tǒng)的電信領(lǐng)域


IP層及以下,例如路由器、交換機(jī)、防火墻、基站等設(shè)備都是采用硬件解決方案。基于專用網(wǎng)絡(luò)處理器(NP),有基于FPGA,更有基于ASIC的。但是基于硬件的劣勢(shì)非常明顯,發(fā)生Bug不易修復(fù),不易調(diào)試維護(hù),并且網(wǎng)絡(luò)技術(shù)一直在發(fā)展,例如2G/3G/4G/5G等移動(dòng)技術(shù)的革新,這些屬于業(yè)務(wù)的邏輯基于硬件實(shí)現(xiàn)太痛苦,不能快速迭代。傳統(tǒng)領(lǐng)域面臨的挑戰(zhàn)是急需一套軟件架構(gòu)的高性能網(wǎng)絡(luò)IO開發(fā)框架。


2.?云的發(fā)展


私有云的出現(xiàn)通過網(wǎng)絡(luò)功能虛擬化(NFV)共享硬件成為趨勢(shì),NFV的定義是通過標(biāo)準(zhǔn)的服務(wù)器、標(biāo)準(zhǔn)交換機(jī)實(shí)現(xiàn)各種傳統(tǒng)的或新的網(wǎng)絡(luò)功能。急需一套基于常用系統(tǒng)和標(biāo)準(zhǔn)服務(wù)器的高性能網(wǎng)絡(luò)IO開發(fā)框架。



3.?單機(jī)性能的飆升


網(wǎng)卡從1G到100G的發(fā)展,CPU從單核到多核到多CPU的發(fā)展,服務(wù)器的單機(jī)能力通過橫行擴(kuò)展達(dá)到新的高點(diǎn)。但是軟件開發(fā)卻無法跟上節(jié)奏,單機(jī)處理能力沒能和硬件門當(dāng)戶對(duì),如何開發(fā)出與時(shí)并進(jìn)高吞吐量的服務(wù),單機(jī)百萬千萬并發(fā)能力。即使有業(yè)務(wù)對(duì)QPS要求不高,主要是CPU密集型,但是現(xiàn)在大數(shù)據(jù)分析、人工智能等應(yīng)用都需要在分布式服務(wù)器之間傳輸大量數(shù)據(jù)完成作業(yè)。這點(diǎn)應(yīng)該是我們互聯(lián)網(wǎng)后臺(tái)開發(fā)最應(yīng)關(guān)注,也最關(guān)聯(lián)的。

二、Linux x86網(wǎng)絡(luò)IO瓶頸

根據(jù)經(jīng)驗(yàn),在C1(8核)上跑應(yīng)用每1W包處理需要消耗1%軟中斷CPU,這意味著單機(jī)的上限是100萬PPS(Packet Per Second)。從TGW(Netfilter版)的性能100萬PPS,AliLVS優(yōu)化了也只到150萬PPS,并且他們使用的服務(wù)器的配置還是比較好的。假設(shè),我們要跑滿10GE網(wǎng)卡,每個(gè)包64字節(jié),這就需要2000萬PPS。


:以太網(wǎng)萬兆網(wǎng)卡速度上限是1488萬PPS,因?yàn)樽钚笮?4B

《Bandwidth, Packets Per Second, and Other Network Performance Metrics》


100G是2億PPS,即每個(gè)包的處理耗時(shí)不能超過50納秒。而一次Cache Miss,不管是TLB、數(shù)據(jù)Cache、指令Cache發(fā)生Miss,回內(nèi)存讀取大約65納秒,NUMA體系下跨Node通訊大約40納秒。所以,即使不加上業(yè)務(wù)邏輯,即使純收發(fā)包都如此艱難。我們要控制Cache的命中率,我們要了解計(jì)算機(jī)體系結(jié)構(gòu),不能發(fā)生跨Node通訊。



從這些數(shù)據(jù),我希望可以直接感受一下這里的挑戰(zhàn)有多大,理想和現(xiàn)實(shí),我們需要從中平衡。問題都有這些


  • 傳統(tǒng)的收發(fā)報(bào)文方式都必須采用硬中斷來做通訊,每次硬中斷大約消耗100微秒,這還不算因?yàn)榻K止上下文所帶來的Cache Miss。

  • 數(shù)據(jù)必須從內(nèi)核態(tài)用戶態(tài)之間切換拷貝帶來大量CPU消耗,全局鎖競(jìng)爭(zhēng)。

  • Linux協(xié)議棧處理路徑長(zhǎng),多核擴(kuò)展性不足,系統(tǒng)調(diào)用開銷大。

  • 內(nèi)核工作在多核上,為可全局一致,即使采用Lock Free,也避免不了鎖總線、內(nèi)存屏障帶來的性能損耗。

  • 從網(wǎng)卡到業(yè)務(wù)進(jìn)程,經(jīng)過的路徑太長(zhǎng),有些其實(shí)未必要的,例如netfilter框架,這些都帶來一定的消耗,而且容易Cache Miss。


三、DPDK的基本原理

從前面的分析可以得知IO實(shí)現(xiàn)的方式、內(nèi)核的瓶頸,以及數(shù)據(jù)流過內(nèi)核存在不可控因素,這些都是在內(nèi)核中實(shí)現(xiàn),內(nèi)核是導(dǎo)致瓶頸的原因所在,要解決問題需要繞過內(nèi)核。所以主流解決方案都是旁路網(wǎng)卡IO,繞過內(nèi)核直接在用戶態(tài)收發(fā)包來解決內(nèi)核的瓶頸。


Linux社區(qū)也提供了旁路機(jī)制Netmap,官方數(shù)據(jù)10G網(wǎng)卡1400萬PPS,但是Netmap沒廣泛使用。其原因有幾個(gè):


  1. Netmap需要驅(qū)動(dòng)的支持,即需要網(wǎng)卡廠商認(rèn)可這個(gè)方案。

  2. Netmap仍然依賴中斷通知機(jī)制,沒完全解決瓶頸。

  3. Netmap更像是幾個(gè)系統(tǒng)調(diào)用,實(shí)現(xiàn)用戶態(tài)直接收發(fā)包,功能太過原始,沒形成依賴的網(wǎng)絡(luò)開發(fā)框架,社區(qū)不完善。


那么,我們來看看發(fā)展了十幾年的DPDK,從Intel主導(dǎo)開發(fā),到華為、思科、AWS等大廠商的加入,核心玩家都在該圈子里,擁有完善的社區(qū),生態(tài)形成閉環(huán)。早期,主要是傳統(tǒng)電信領(lǐng)域3層以下的應(yīng)用,如華為、中國(guó)電信、中國(guó)移動(dòng)都是其早期使用者,交換機(jī)、路由器、網(wǎng)關(guān)是主要應(yīng)用場(chǎng)景。但是,隨著上層業(yè)務(wù)的需求以及DPDK的完善,在更高的應(yīng)用也在逐步出現(xiàn),尤其當(dāng)前云計(jì)算領(lǐng)域(網(wǎng)絡(luò)吞吐量巨大),已經(jīng)成為云網(wǎng)絡(luò)主要的核心技術(shù)之一。



DPDK旁路原理


左邊是內(nèi)核協(xié)議棧:

?網(wǎng)卡 -> 驅(qū)動(dòng) -> 協(xié)議棧 -> Socket接口 -> 業(yè)務(wù)


右邊是DPDK的方式(基于UIO(Userspace I/O)旁路數(shù)據(jù)):

網(wǎng)卡 -> DPDK輪詢模式-> DPDK基礎(chǔ)庫(kù) -> 業(yè)務(wù)


用戶態(tài)的好處是易用開發(fā)和維護(hù),靈活性好。并且Crash也不影響內(nèi)核運(yùn)行,魯棒性強(qiáng)。



而DPDK不光是bypass 內(nèi)核協(xié)議棧,還無所不及地采用各種手段,把凡是能夠影響的網(wǎng)絡(luò)IO性能的瓶頸點(diǎn)都做了極致的優(yōu)化。


DPDK架構(gòu)


核心模塊


  • 環(huán)境抽象層

? ? ? 環(huán)境抽象層 (EAL) 提供了一個(gè)通用接口,該接口對(duì)應(yīng)用程序和庫(kù)隱藏了環(huán)境細(xì)? ? ? ? 節(jié)。EAL 提供的服務(wù)是:

  • DPDK 加載和啟動(dòng)

  • 支持多進(jìn)程和多線程執(zhí)行類型

  • 核心關(guān)聯(lián)/分配程序

  • 系統(tǒng)內(nèi)存分配/解除分配

  • 原子/鎖操作

  • 時(shí)間參考

  • PCI總線訪問

  • 跟蹤和調(diào)試功能

  • CPU特性識(shí)別

  • 中斷處理

  • 報(bào)警操作

  • 內(nèi)存管理(malloc)


  • 環(huán)管理器 (librte_ring)

    環(huán)形結(jié)構(gòu)在有限大小的表中提供了一個(gè)無鎖的多生產(chǎn)者、多消費(fèi)者 FIFO API。它比無鎖隊(duì)列有一些優(yōu)勢(shì);更容易實(shí)施,適應(yīng)批量操作,速度更快。環(huán)由內(nèi)存池管理器 (librte_mempool)?使用,并可用作核心和/或邏輯核心上連接在一起的執(zhí)行塊之間的通用通信機(jī)制。

  • 內(nèi)存池管理器 (librte_mempool)

    內(nèi)存池管理器負(fù)責(zé)分配內(nèi)存中的對(duì)象池。池由名稱標(biāo)識(shí)并使用環(huán)來存儲(chǔ)空閑對(duì)象,它提供了一些其他可選服務(wù),例如每核對(duì)象緩存和對(duì)齊助手,以確保填充對(duì)象以在所有 RAM 通道上均勻分布它們。

  • 網(wǎng)絡(luò)數(shù)據(jù)包緩沖區(qū)管理 (librte_mbuf)

    mbuf 庫(kù)提供了創(chuàng)建和銷毀緩沖區(qū)的功能,DPDK 應(yīng)用程序可以使用這些緩沖區(qū)來存儲(chǔ)消息緩沖區(qū)。消息緩沖區(qū)在啟動(dòng)時(shí)創(chuàng)建并存儲(chǔ)在內(nèi)存池中,使用 DPDK 內(nèi)存池庫(kù)。該庫(kù)提供了一個(gè) API 來分配/釋放 mbuf,操作用于承載網(wǎng)絡(luò)數(shù)據(jù)包的數(shù)據(jù)包緩沖區(qū)。

  • 定時(shí)器管理器 (librte_timer)

    該庫(kù)為 DPDK 執(zhí)行單元提供定時(shí)器服務(wù),提供異步執(zhí)行功能的能力。它可以是周期性的函數(shù)調(diào)用,也可以是一次性調(diào)用。它使用環(huán)境抽象層 (EAL) 提供的計(jì)時(shí)器接口來獲取精確的時(shí)間參考,并且可以根據(jù)需要在每個(gè)內(nèi)核的基礎(chǔ)上啟動(dòng)。

  • ?以太網(wǎng)* 輪詢模式驅(qū)動(dòng)程序架構(gòu)

    DPDK 包括用于 1 GbE、10 GbE 和 40 GbE 的輪詢模式驅(qū)動(dòng)程序 (PMD),以及半虛擬化的 virtio 以太網(wǎng)控制器,這些控制器旨在在沒有異步、基于中斷的信號(hào)機(jī)制的情況下工作。

  • 數(shù)據(jù)包轉(zhuǎn)發(fā)算法支持

    DPDK 包括哈希(librte_hash)和最長(zhǎng)前綴匹配(LPM,librte_lpm)庫(kù),以支持相應(yīng)的數(shù)據(jù)包轉(zhuǎn)發(fā)算法。

  • librte_net

    librte_net 庫(kù)是 IP 協(xié)議定義和便利宏的集合。它基于 FreeBSD* IP 堆棧中的代? ? 碼,包含協(xié)議編號(hào)(用于 IP 標(biāo)頭)、IP 相關(guān)宏、IPv4/IPv6 標(biāo)頭結(jié)構(gòu)以及 TCP、UDP 和 SCTP 標(biāo)頭結(jié)構(gòu)。

優(yōu)化技術(shù)


  • PMD用戶態(tài)驅(qū)動(dòng),使用無中斷方式直接操作網(wǎng)卡的接收和發(fā)送隊(duì)列;

  • 采用HugePage減少TLB Miss;

  • DPDK采用向量SIMD指令優(yōu)化性能;

  • CPU親緣性和獨(dú)占;

  • 內(nèi)存對(duì)齊:根據(jù)不同存儲(chǔ)硬件的配置來優(yōu)化程序,確保對(duì)象位于不同channel和rank的起始地址,這樣能保證對(duì)象并并行加載,性能也能夠得到極大的提升;

  • Cache對(duì)齊,提高cache訪問效率:

  • NUMA親和,提高numa內(nèi)存訪問性能;

  • 減少進(jìn)程上下文切換:保證活躍進(jìn)程數(shù)目不超過CPU個(gè)數(shù);減少堵塞函數(shù)的調(diào)用,盡量采樣無鎖數(shù)據(jù)結(jié)構(gòu);

  • 利用空間局部性,采用預(yù)取Prefetch,在數(shù)據(jù)被用到之前就將其調(diào)入緩存,增加緩存命中率;

  • 充分挖掘網(wǎng)卡的潛能:借助現(xiàn)代網(wǎng)卡支持的分流(RSS, FDIR)和卸載(TSO,chksum)等特性;

DPDK支持的CPU體系架構(gòu)

x86、ARM、PowerPC(PPC)


DPDK支持的網(wǎng)卡列表

https://core.dpdk.org/supported



四、DPDK的基石UIO


為了讓驅(qū)動(dòng)運(yùn)行在用戶態(tài),Linux提供UIO機(jī)制。使用UIO可以通過read感知中斷,通過mmap實(shí)現(xiàn)和網(wǎng)卡的通訊。



UIO(Userspace I/O)是運(yùn)行在用戶空間的I/O技術(shù)。Linux系統(tǒng)中一般的驅(qū)動(dòng)設(shè)備都是運(yùn)行在內(nèi)核空間,而在用戶空間用應(yīng)用程序調(diào)用即可,而UIO則是將驅(qū)動(dòng)的很少一部分運(yùn)行在內(nèi)核空間,而在用戶空間實(shí)現(xiàn)驅(qū)動(dòng)的絕大多數(shù)功能!使用UIO可以避免設(shè)備的驅(qū)動(dòng)程序需要隨著內(nèi)核的更新而更新的問題.通過UIO的運(yùn)行原理圖可以看出,用戶空間下的驅(qū)動(dòng)程序比運(yùn)行在內(nèi)核空間的驅(qū)動(dòng)要多得多,UIO框架下運(yùn)行在內(nèi)核空間的驅(qū)動(dòng)程序所做的工作比較簡(jiǎn)單。



UIO原理:




要開發(fā)用戶態(tài)驅(qū)動(dòng)有幾個(gè)步驟:

1.開發(fā)運(yùn)行在內(nèi)核的UIO模塊(分配和記錄設(shè)備需要的資源和注冊(cè)u(píng)io設(shè)備),因?yàn)橛仓袛嘀荒茉趦?nèi)核處理;

2.通過/dev/uioX讀取中斷;

3.通過mmap和外設(shè)共享內(nèi)存,實(shí)現(xiàn)零拷貝;


五、DPDK核心優(yōu)化:PMD

UIO旁路了內(nèi)核,主動(dòng)輪詢?nèi)サ粲仓袛啵珼PDK從而可以在用戶態(tài)做收發(fā)包處理。帶來Zero Copy、無系統(tǒng)調(diào)用的好處,同步處理減少上下文切換帶來的Cache Miss。


運(yùn)行在PMD的Core會(huì)處于用戶態(tài)CPU100%的狀態(tài)




網(wǎng)絡(luò)空閑時(shí)CPU長(zhǎng)期空轉(zhuǎn),會(huì)帶來能耗問題。所以,DPDK推出Interrupt DPDK模式。



Interrupt DPDK:


圖片引自David Su/Yunhong Jiang/Wei Wang的文檔《Towards Low Latency Interrupt Mode DPDK》



它的原理和NAPI很像,就是沒包可處理時(shí)進(jìn)入睡眠,改為中斷通知。并且可以和其他進(jìn)程共享同個(gè)CPU Core,但是DPDK進(jìn)程會(huì)有更高調(diào)度優(yōu)先級(jí)。

六、DPDK的高性能代碼實(shí)現(xiàn)

1.?采用HugePage減少TLB Miss



默認(rèn)下Linux采用4KB為一頁(yè),頁(yè)越小內(nèi)存越大,頁(yè)表的開銷越大,頁(yè)表的內(nèi)存占用也越大。CPU有TLB(Translation Lookaside Buffer)成本高所以一般就只能存放幾百到上千個(gè)頁(yè)表項(xiàng)。如果進(jìn)程要使用64G內(nèi)存,則64G/4KB=16000000(一千六百萬)頁(yè),每頁(yè)在頁(yè)表項(xiàng)中占用16000000 * 4B=62MB。如果用HugePage采用2MB作為一頁(yè),只需64G/2MB=2000,數(shù)量不在同個(gè)級(jí)別。





而DPDK采用HugePage,在x86-64下支持2MB、1GB的頁(yè)大小,幾何級(jí)的降低了頁(yè)表項(xiàng)的大小,從而減少TLB-Miss。并提供了內(nèi)存池(Mempool)、MBuf、無鎖環(huán)(Ring)、Bitmap等基礎(chǔ)庫(kù)。根據(jù)我們的實(shí)踐,在數(shù)據(jù)平面(Data Plane)頻繁的內(nèi)存分配釋放,必須使用內(nèi)存池,不能直接使用rte_malloc,DPDK的內(nèi)存分配實(shí)現(xiàn)非常簡(jiǎn)陋,不如ptmalloc。



2.?SNA(Shared-nothing Architecture)


軟件架構(gòu)去中心化,盡量避免全局共享,帶來全局競(jìng)爭(zhēng),失去橫向擴(kuò)展的能力。NUMA體系下不跨Node遠(yuǎn)程使用內(nèi)存。



3.?SIMD(Single Instruction Multiple Data)



從最早的mmx/sse到最新的avx2,SIMD的能力一直在增強(qiáng)。DPDK采用批量同時(shí)處理多個(gè)包,再用向量編程,一個(gè)周期內(nèi)對(duì)所有包進(jìn)行處理。比如,memcpy就使用SIMD來提高速度。SIMD在游戲后臺(tái)比較常見,但是其他業(yè)務(wù)如果有類似批量處理的場(chǎng)景,要提高性能,也可看看能否滿足。



4.?不使用慢速API


這里需要重新定義一下慢速API,比如說gettimeofday,雖然在64位下通過vDSO已經(jīng)不需要陷入內(nèi)核態(tài),只是一個(gè)純內(nèi)存訪問,每秒也能達(dá)到幾千萬的級(jí)別。但是,不要忘記了我們?cè)?0GE下,每秒的處理能力就要達(dá)到幾千萬。所以即使是gettimeofday也屬于慢速API。DPDK提供Cycles接口,例如rte_get_tsc_cycles接口,基于HPET或TSC實(shí)現(xiàn)。


在x86-64下使用RDTSC指令,直接從寄存器讀取,需要輸入2個(gè)參數(shù),比較常見的實(shí)現(xiàn):


這么寫邏輯沒錯(cuò),但是還不夠極致,還涉及到2次位運(yùn)算才能得到結(jié)果,我們看看DPDK是怎么實(shí)現(xiàn):


巧妙的利用C的union共享內(nèi)存,直接賦值,減少了不必要的運(yùn)算。但是使用tsc有些問題需要面對(duì)和解決



1) CPU親和性,解決多核跳動(dòng)不精確的問題

2) 內(nèi)存屏障,解決亂序執(zhí)行不精確的問題

3) 禁止降頻和禁止Intel Turbo Boost,固定CPU頻率,解決頻率變化帶來的失準(zhǔn)問題



5.?編譯執(zhí)行優(yōu)化



1) 分支預(yù)測(cè)





現(xiàn)代CPU通過pipeline、superscalar提高并行處理能力,為了進(jìn)一步發(fā)揮并行能力會(huì)做分支預(yù)測(cè),提升CPU的并行能力。遇到分支時(shí)判斷可能進(jìn)入哪個(gè)分支,提前處理該分支的代碼,預(yù)先做指令讀取編碼讀取寄存器等,預(yù)測(cè)失敗則預(yù)處理全部丟棄。我們開發(fā)業(yè)務(wù)有時(shí)候會(huì)非常清楚這個(gè)分支是true還是false,那就可以通過人工干預(yù)生成更緊湊的代碼提示CPU分支預(yù)測(cè)成功率。



2) CPU Cache預(yù)取

Cache Miss的代價(jià)非常高,回內(nèi)存讀需要65納秒,可以將即將訪問的數(shù)據(jù)主動(dòng)推送的CPU Cache進(jìn)行優(yōu)化。比較典型的場(chǎng)景是鏈表的遍歷,鏈表的下一節(jié)點(diǎn)都是隨機(jī)內(nèi)存地址,所以CPU肯定是無法自動(dòng)預(yù)加載的。但是我們?cè)谔幚肀竟?jié)點(diǎn)時(shí),可以通過CPU指令將下一個(gè)節(jié)點(diǎn)推送到Cache里。


API文檔:https://doc.dpdk.org/api/rte__prefetch_8h.html


3) 內(nèi)存對(duì)齊



內(nèi)存對(duì)齊有2個(gè)好處:


3.1 避免結(jié)構(gòu)體成員跨Cache Line,需2次讀取才能合并到寄存器中,降低性能。結(jié)構(gòu)體成員需從大到小排序和以及強(qiáng)制對(duì)齊。


參考《Data alignment: Straighten up and fly right》


3.2 多線程場(chǎng)景下寫產(chǎn)生False sharing,造成Cache Miss,結(jié)構(gòu)體按Cache Line對(duì)齊



4) 常量?jī)?yōu)化


常量相關(guān)的運(yùn)算的編譯階段完成。比如C 11引入了constexp,比如可以使用GCC的__builtin_constant_p來判斷值是否常量,然后對(duì)常量進(jìn)行編譯時(shí)得出結(jié)果。舉例網(wǎng)絡(luò)序主機(jī)序轉(zhuǎn)換

其中rte_constant_bswap32的實(shí)現(xiàn)


5)使用CPU指令


現(xiàn)代CPU提供很多指令可直接完成常見功能,比如大小端轉(zhuǎn)換,x86有bswap指令直接支持了。


這個(gè)實(shí)現(xiàn),也是GLIBC的實(shí)現(xiàn),先常量?jī)?yōu)化、CPU指令優(yōu)化、最后才用裸代碼實(shí)現(xiàn)。畢竟都是頂端程序員,對(duì)語言、編譯器,對(duì)實(shí)現(xiàn)的追求不一樣,所以造輪子前一定要先了解好輪子。



Google開源的cpu_features可以獲取當(dāng)前CPU支持什么特性,從而對(duì)特定CPU進(jìn)行執(zhí)行優(yōu)化。高性能編程永無止境,對(duì)硬件、內(nèi)核、編譯器、開發(fā)語言的理解要深入且與時(shí)俱進(jìn)。

七、DPDK生態(tài)

對(duì)我們互聯(lián)網(wǎng)后臺(tái)開發(fā)來說DPDK框架本身提供的能力還是比較裸的,比如要使用DPDK就必須實(shí)現(xiàn)TCP/IP協(xié)議棧(ARP,IP,TCP/UDP, socket等)這些基礎(chǔ)功能,有一定上手難度。如果要更高層的業(yè)務(wù)使用,還需要用戶態(tài)的協(xié)議棧支持。不建議直接使用DPDK。



應(yīng)用


目前生態(tài)完善,社區(qū)強(qiáng)大(一線大廠支持)的應(yīng)用層開發(fā)項(xiàng)目是FD.io(The Fast Data Project),有思科開源支持的VPP,比較完善的協(xié)議支持,ARP、VLAN、Multipath、IPv4/v6、MPLS等。用戶態(tài)傳輸協(xié)議UDP/TCP有TLDK。從項(xiàng)目定位到社區(qū)支持力度算比較靠譜的框架。


Fd.io: The Universal Dataplane


FD.io(快速數(shù)據(jù) - 輸入/輸出)是多個(gè)項(xiàng)目和庫(kù)的集合,用于擴(kuò)展基于數(shù)據(jù)平面開發(fā)套件 (DPDK) 的應(yīng)用,以在通用硬件平臺(tái)上支持靈活、可編程和可組合的服務(wù)。FD.io 為軟件定義基礎(chǔ)設(shè)施開發(fā)人員社區(qū)提供了一個(gè)登陸站點(diǎn),其中包含多個(gè)項(xiàng)目:



促進(jìn)基于軟件的數(shù)據(jù)包處理的創(chuàng)新,以創(chuàng)建適用于許多架構(gòu)(x86、ARM、 PowerPC)和部署環(huán)境(裸機(jī)、VM、容器)。


騰訊云開源的F-Stack也值得關(guān)注一下,開發(fā)更簡(jiǎn)單,直接提供了POSIX接口。



F-Stack是一個(gè)基于DPDK的開源高性能網(wǎng)絡(luò)框架,具有以下特點(diǎn):

  1. 網(wǎng)卡滿載時(shí)可以達(dá)到的超高網(wǎng)絡(luò)性能:1000萬并發(fā)連接,500萬RPS,100萬CPS。

  2. 移植FreeBSD 11.01用戶空間堆棧,提供完整的堆棧功能,并刪減了大量無關(guān)功能。這大大提高了網(wǎng)絡(luò)性能。

  3. 支持Nginx、Redis等成熟應(yīng)用。服務(wù)可以輕松使用 F-Stack。

  4. 易于擴(kuò)展的多進(jìn)程架構(gòu)。

  5. 提供微線程接口。各種有狀態(tài)應(yīng)用程序可以輕松使用 F-Stack 來獲得高性能,而無需處理復(fù)雜的異步邏輯。

  6. 提供 Epoll/Kqueue 接口,允許多種應(yīng)用輕松使用 F-Stack。


Seastar也很強(qiáng)大和靈活,內(nèi)核態(tài)和DPDK都隨意切換,也有自己的傳輸協(xié)議Seastar Native TCP/IP Stack支持,但是目前還未看到有大型項(xiàng)目在使用Seastar,可能需要填的坑比較多。




?Seastar 目前專注于高吞吐量、低延遲的 I/O 密集型應(yīng)用程序。


  • Pedis?: Redis 兼容的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)

  • Scylla:NoSQL 列存儲(chǔ)數(shù)據(jù)庫(kù),以 10 倍的吞吐量與 Apache Cassandra 兼容

  • Seastar HTTPD:網(wǎng)絡(luò)服務(wù)器

  • Seastar Memcached:Memcache 鍵值存儲(chǔ)的快速服務(wù)器


Open vSwitch?(OVS)高性能開源虛擬交換機(jī), 可以利用DPDK這些功能繞過 Linux 內(nèi)核OVS 處理,增強(qiáng)OVS的IO性能,官方數(shù)據(jù)顯示,可以提高9倍以上的性能提升.



八、高性能編程技術(shù)和代碼優(yōu)化

性能評(píng)估公式

  • IPP?表示代碼的復(fù)雜程度,IPC?表示代碼執(zhí)行的效率

  • 2G主頻CPU處理10G網(wǎng)卡達(dá)到線速?2GHz/14.8Mpps =134 clock cycles


1.用戶空間輪詢


  • 減少中斷帶來開銷;

  • 減少系統(tǒng)調(diào)用帶來開銷;

  • 零拷貝減少內(nèi)存拷貝的時(shí)間;

  • 輪詢 Polling,busy looping 提供了I/O批量處理的可能性;

  • 避免中斷性能瓶頸是DPDK提升數(shù)據(jù)包處理速度的關(guān)鍵之一;


2.多核CPU性能優(yōu)化


  • RSS硬件隊(duì)列;

  • CPU獨(dú)占:獨(dú)占CPU資源,減少調(diào)度影響,提高系統(tǒng)性能;

  • CPU綁定:減少CPU上下文切換,提高系統(tǒng)性能;

  • 中斷親和 :?中斷負(fù)載均衡,減輕其他CPU負(fù)擔(dān),提高系統(tǒng)性能;

  • 進(jìn)程親和:減少CPU上下文切換,提高系統(tǒng)性能;

  • 中斷隔離:減少中斷對(duì)CPU調(diào)度影響,提高系統(tǒng)性能;

  • Per CPU:Per-CPU是基于空間換時(shí)間的方法, 讓每個(gè)CPU都有自己的私有數(shù)據(jù)段(放在L1中),并將一些變量私有化到?每個(gè)CPU的私有數(shù)據(jù)段中. 單個(gè)CPU在訪問自己的私有數(shù)據(jù)段時(shí), 不需要考慮其他CPU之間的競(jìng)爭(zhēng)問題,也不存在同步的問題. ?注意只有在該變量在各個(gè)CPU上邏輯獨(dú)立時(shí)才可使用;



3. 鎖優(yōu)化


  • 無鎖數(shù)據(jù)結(jié)構(gòu),將并發(fā)最大化;

  • Per-CPU設(shè)計(jì),盡量避免資源競(jìng)爭(zhēng);

  • 采用RCU機(jī)制,讀寫共享數(shù)據(jù)可以無鎖并行;

? ? ? ?深入理解RCU|核心原理

  • spinlock,采用非阻塞鎖,防止上下文切換導(dǎo)致cache miss;

  • 采用CAS原子操作(Compare and Swap)進(jìn)行無鎖設(shè)計(jì);


4.批量處理


  • 輪詢機(jī)制允許一次接收或發(fā)送多個(gè)報(bào)文;

  • 批量處理分?jǐn)偟慕邮栈虬l(fā)送操作本身的開銷;

  • 絕大部分報(bào)文需要做相同或相似的計(jì)算處理,意味著相同的指令會(huì)被反復(fù)地執(zhí)行,報(bào)文的批量計(jì)算分?jǐn)偭撕瘮?shù)調(diào)用的上下文切換,堆棧的初始化等等開銷,同時(shí)大大減少了l1i cache miss

  • 對(duì)于某一個(gè)函數(shù),l1icache miss?僅僅發(fā)生在第一個(gè)報(bào)文被處理的時(shí)刻

  • 批量計(jì)算提供了更好的代碼優(yōu)化可能性(數(shù)據(jù)預(yù)取,多重循環(huán)等)


5.Cache優(yōu)化


  • CPU的速度遠(yuǎn)遠(yuǎn)大于RAM的速度

  • 程序在運(yùn)行時(shí)具有局部性規(guī)律

? ? ? ? 時(shí)間局部性,很快還會(huì)訪問

? ? ? ? 空間局部性,相鄰也會(huì)訪問

  • 不同級(jí)別cache速度差異?L1 > L2 > L3

  • 減少Cache Miss是提升性能的關(guān)鍵

  • Cache?層次化結(jié)構(gòu)


?

  • iCacheMiss?常常被忽略

? ? ? ?更優(yōu)的代碼,編譯器優(yōu)化選項(xiàng)

? ? ? ?更小的代碼尺寸

? ? ? ?更好的代碼布局-?分支預(yù)測(cè)


  • 代碼布局影響iCache命中率


????????????B 段代碼較少會(huì)被調(diào)用


  • Cache一致性問題

    原則是避免多個(gè)核訪問同一個(gè)內(nèi)存地址或數(shù)據(jù)結(jié)構(gòu)

    在數(shù)據(jù)結(jié)構(gòu)上,每個(gè)核都有獨(dú)立的數(shù)據(jù)結(jié)構(gòu)

    多個(gè)核訪問同一個(gè)網(wǎng)卡:每個(gè)核都創(chuàng)建單獨(dú)的接收隊(duì)列和發(fā)送隊(duì)列



6. 代碼優(yōu)化技巧

  • Cache Line 對(duì)齊,減少dCache miss,?避免偽共享;

  • 數(shù)據(jù)預(yù)取,減少dCache miss, prefetch 指令;

  • 分支預(yù)測(cè),優(yōu)化代碼布局,?提高CPU流水線效率;??????

  • 函數(shù)內(nèi)聯(lián),減少函數(shù)調(diào)用開銷;

  • CPU擴(kuò)展指令集SIMD:sse,avx,減少指令數(shù)量,最大化的利用一級(jí)緩存訪存的帶寬;

  • 多重循環(huán)處理報(bào)文,更好地優(yōu)化CPU流水線;

  • 編譯器優(yōu)化;


????????????????????????參考

GBN手札 - 一文看懂DPD

https://feisky.gitbooks.io/sdn

https://www.dpdk.org/

http://doc.dpdk.org/guides/prog_guide/index.html

最后

DPDK的內(nèi)容遠(yuǎn)不止如此,如果對(duì)DPDK感興趣可以參考更多內(nèi)容:

DPDK官網(wǎng)

https://www.dpdk.org/

DPDK源碼

https://github.com/DPDK/dpdk

DPDK編程指南

http://doc.dpdk.org/guides/prog_guide/index.html

經(jīng)典書籍推薦

深入淺出DPDK

轉(zhuǎn)自:極客重生

- EOF -

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉