因爲TCP/IP是使用最廣泛的Internet協議,下面只集中討論TCP/IP 棧和以太網(Ethernet)。術語 LinuxTCP/IP棧和 Linux網絡棧可互換使用,由於 TCP/IP棧是 Linux內核的組成部分,也被看做是 Linux默認的網絡棧。 程序員
1、實例分析中使用的基準測試
web
一、 NetBench數據庫
NetBench是一種 Ziff-Davis基準測試, 能夠測量文件服務器對來自客戶端(向服務器提交網絡文件操做的請求)的遠程文件 I/O請求進行處理的程度。NetBench報告關於吞吐率和客戶響應時間的測量結果。該基準測試主要用於測量 LinuxTCP/IP發送端(NetBench服務器)的吞吐率性能,由於對於該基準測試而言,接收端客戶是 32位的 Windows客戶。性能優化
二、 Netperf3
Netperf3是一種測試 Linux網絡吞吐率和網絡擴展性的微型基準測試。試驗版本可從 http://www.netperf.org獲取。該版本提供了多線程支持。 IBM公司對 Netperf3的功能加以加強,使其包含了對多網卡(NIC)和多客戶的支持。添加這兩個特性是爲了測量Linux網絡 SMP和網卡的擴展性。 IBM公司還添加了另外一個可旁路 TCP/IP棧的接口,用於測試網絡驅動程序。 Netperf3所測的度量是吞吐率(以每秒兆位爲單位)。服務器
2、Linux 2.6 內核中的加強機制網絡
在當前的計算機系統裏,互連總線速度和內存訪問延遲並無與處理器速度(GHz)和網絡帶寬容量(吉比特網絡)成比例增加。減小對互連總線和內存等相對慢速部件的訪問次數一般能夠改進系統(包括網絡)的性能。在 TCP/IP棧中, 做爲傳輸和接收過程的組成部分,會發生屢次數據複製操做,從而在互連總線中產生巨大流量。這些流量引發訪存次數的增長,從而致使低下的網絡性能和擴展性問題。在 SMP 和 NUMA系統中, 額外的高速CPU與相對慢速的互連總線之間的矛盾進一步加重了擴展性問題 。
總線速率、總線吞吐率以及工做負荷生成的總線流量對於改進 Linux網絡棧的性能相當重要。爲了消除或減小數據流經總線的次數以及爲了減小訪存次數而對 Linux網絡棧實施的任何改進均可以改善 Linux軟件棧性能。下面分析2.6內核實現的一些加強特性,這些特性減小了在 TCP/IP 協議棧中執行的複製次數,從而提升了網絡棧性能。這些加強特性具體包括如下內容:多線程
- SendFile支持
- TCP分段卸載(TCP SegmentationOffloading, TSO)支持
- 進程和 IRQ親合度
- 網絡設備驅動程序 API(NAPI)
- TCP卸載引擎(TCP OffloadEngine, TOE
一、SendFile
Linux 2.4網絡棧支持 SendFileAPI,容許經過直接內存訪問(DMA)機制將應用數據從文件系統緩衝區 cache直接發送到網卡緩衝區。 經過使用網絡棧和網絡接口卡(NIC)中的 Zerocopy功能支持,SendFileAPI能夠將應用數據經過 DMA直接發送到網絡上進行傳輸,而沒必要執行一般的用戶空間到內核空間的複製操做。在典型的無 SendFile支持的狀況下, 應用程序發送文件的步驟以下:
- 分配一個緩衝區。
- 將文件數據複製到緩衝區中(首先將文件數據從磁盤複製到內核緩衝區 cache,然後再複製到應用程序的緩衝區)。
- 對複製到內核 socket緩衝區中的數據執行發送操做。
- 獲取到達 NIC的 DMA。
SendFileAPI和 Zerocopy能夠旁路多餘的複製操做,從而減小了涉及到許多複雜且CPU密集的操做的上下文切換過程。另外,相同數據的多個副本若是在多個 CPU中被處理, 則會增長內存延遲、 cache不命中率以及地址轉換後備緩衝器(translation lookasidebuffer, TLB)cache不命中率, 從而對性能產生負面影響。 額外複製的直接和間接後果會致使網絡性能低下。
如名字所示,SendFileAPI只能傳輸文件系統數據。所以,諸如 Web服務器、Telnet等處理動態數據和交互式數據的應用沒法使用這個 API。因爲在 Internet上傳輸的數據大部分是靜態(文件)數據而且文件傳輸是這種通訊的主體部分,所以 SendFile API 和Zerocopy對於改進網絡應用的性能很是重要。適當地使用了 SendFile和 Zerocopy的應用程序可以極大地改進網絡性能。
Linux 中對 SendFile API 的支持以及在 Linux TCP/IP 棧和網絡驅動程序中對Zerocopy的支持實現了在 TCP/IP 數據處理過程當中的單次複製機制。SendFile對於應用程序是不透明的,由於應用程序須要實現這個 API以便利用該特性。
二、 TCP分段卸載socket
對於網絡報文的每次 TCP/IP傳輸或接收過程,當數據被傳輸到 NIC或者從 NIC接收時會發生屢次 PCI總線訪問操做。經過使用 NIC和 Linux TCP/IP棧中的 TCP分段卸載(TCPSegmentation Offloading, TSO)特性,對於以太網而言,發送端的 PCI總線訪問次數減至對於每一個 64KB大小緩衝區訪問一次而不是對每一個網絡報文(1518B)都訪問一次。 若是應用程序提供的緩衝區長度大於幀長度, 則 TCP/IP棧將其劃分紅多個幀,爲 每個幀都添加一個 TCP/IP頭部,並將其經過DMA映射到 NIC。
若是使能了 TSO特性, 則爲 64KB數據封裝一個僞報文頭, 並經過 DMA將其發送至 NIC。 網絡適配器的控制器將這個 64KB數據塊解析成標準的以太網報文,從而減小了主機的 CPU利用率和對 PCI總線的訪問。 TSO經過下降 CPU利用率和提升網絡吞吐率來改善效率。針對該任務專門設計了網絡芯片(network silicon)。在 Linux以及針對 TSO而設計的 Gigabit Ethernet芯片中激活 TSO特性可以加強系統性能。


三、 網絡負荷中的進程與IRQ親合性
親合性或綁定的含義是指強制只在選定的一個或多個 CPU上執行進程中斷的過程。在多處理器系統中,基於操做系統調度器使用的策略,在特定條件下能夠將一個處理器上的進程遷移到其餘處理器。經過將進程保持在同一個處理器——這強制調度器將某個特定任務調度到指定 CPU上——能夠極大提升所需數據存在於 cache中的機率,從而能夠減小內存延遲。有些狀況下,即便進程被限定在同一個 CPU上調度, 諸如大型工做集以及多進程共享同一個 CPU等因素也經常致使清空 cache,所以進程親合性可能沒法在全部狀況下都起做用。本章給出的實例分析很是適於利用進程親合特性。
Linux內核實現了下列兩個系統調用,以便執行進程與處理器的綁定操做:
asmlinkage int sys_sched_set_affinity(pid_t pid, unsigned int mask_len,unsigned long *new_mask_ptr);
asmlinkage int sys_sched_get_affinity(pid_t pid, unsigned int*user_mask_len_ptr, unsigned long *user_mask_ptr);
sched_set_affinity()系統調用還確保在恰當的一個或多個 CPU 上運行目標進程。sched_get_affinity(pid,&mask_len,NULL)可用於查詢內核所支持的 CPU位屏蔽碼長度。
進程親合性意味着將進程或線程綁定到某個 CPU上。IRQ親合性意味着強制在某個特定 CPU上執行具體 IRQ的中斷處理。在 Linux中可使用/proc接口設置 IRQ親合性。經過肯定 I/O接口所用的 IRQ,而後修改該特定 IRQ的屏蔽碼,能夠設置 IRQ親合性。例如,如下命令將 IRQ 63設置到 CPU 0,並將 IRQ 63所生成的中斷髮送到 CPU 1上
echo "1" > /proc/irq/63/smp_affinity
進程親合性與IRQ親合性是改進應用程序和系統的吞吐率及擴展性的通用性能優化實踐。這些方法都要求識別出一個應用程序的全部進程並對其加以隔離,還須要識別出中斷以便將其映射至應用程序的進程和運行這些進程的處理器。所以,這種「 n對 n」的映射關係在複雜環境下並不總可行。
Netperf3示例分析清晰代表,IRQ與進程親合性的應用改善了Linux網絡的 SMP擴展性和網絡吞吐率性能。在該例子中,使用了 Netperf3的多適配器支持能力來測量網絡擴展性。它對每一個 NIC都建立一個進程, 該進程綁定到 4個 CPU中的某個 CPU以及某個 NIC上。該 NIC將由該進程使用並與之綁定到同一個CPU。一個 Netperf3進程的處理操做是被隔離的,而且對某個 NIC所生成的中斷的執行操做被隔離到單個處理器上。在 Netperf3服務器上使用 TCP_STREAM測試來完成這個過程。
在服務器上,該工做負荷進行繁重的數據接收處理操做,會產生屢次數據拷貝操做(將數據從 NIC複製到內核內存中,再從內核內存中複製到應用內存中)。綁定機制提升了性能,由於這些複製操做在單個處理器上完成,從而無需將數據加載到兩個不一樣的處理器 cache中。若是同時應用這兩個親合性的話,那麼綁定機制能夠減小內存延遲。儘管能夠單獨使用IRQ親合性或進程親合性,但組合使用時可以進一步提升性能。
四、 NAPI
爲了改進在繁重中斷載荷條件下的 Linux網絡性能,開發了網絡設備驅動程序 API(NAPI)。系統的負荷可用於肯定是否採用輪詢(polling)
或中斷機制來處理輸入數據以便改進性能。輪詢機制在中斷負荷較重時能夠改進性能, 但當中斷負荷較輕時會浪費 CPU週期。中斷機制在較低的中斷負荷狀況下能夠改進延遲,但當中斷負荷超過了最大無損轉發率(Maximum Loss Free Forwarding Rate, MLFFR)時,會致使系統對於活鎖(live lock)是脆弱的。NAPI只適用於實現了DMA緩衝區環的 NIC。當網絡報文到達時, NAPI被置入環上的下一個緩衝區中。一般,對於每一個報文, 處理器都會被中斷而且系統從環中清除該報文。當 NAPI被激活時,響應第一個中斷,通知 NIC中止中斷。而後 NAPI在環上輪詢。 NAPI在處理報文過程當中,能夠取出新報文而無需更多中斷,從而極大減小了接收中斷,這有助於系統在繁重的網絡負荷條件下正常運行。
Linux 2.5內核中的 NAPI實現使得網絡設備驅動程序員無需在每一個驅動程序中人工實現輪詢,還能夠管理中斷泛洪,並保護系統免受拒絕服務(Denial of Service, DoS)攻擊。因爲中斷處理程序的 CPU開銷,在沒有 NAPI支持的狀況下泛洪的最高限額要低得多。NAPI也消除了編制大量代碼來實現NIC硬件中斷縮減(interrupt mitigation)解決方案的需求。爲了利用 NAPI的優勢,網絡設備驅動程序須要使用新的網絡 API(NAPI)。當前,許多網絡設備驅動程序都提供對 NAPI的支持。 Intel Gigabit Ethernet等網絡驅動程序將NAPI做爲一個可構建在驅動程序中的選項, 而諸如 BroadComTg3等驅動程序默認地支持 NAPI。若是網絡驅動程序不使用 NAPI特性的話,則內核中的 NAPI代碼也不被使用。
五、 TCP卸載引擎
有些服務器應用程序並未使用LinuxTCP/IP協議的一些獨有特性如IP過濾或服務質量(Quality of Service, QoS), 這些應用可使用支持 TCP/IP卸載特性的網卡來改進網絡性能。TCP卸載引擎(TCPOffloadEngine, TOE)技術包括對現有 TCP/IP協議棧軟件進行擴展,從而可以使用在特殊 TOE網卡(TNIC)上實現的硬件特性。這種硬件/軟件組合容許操做系統將全部 TCP/IP流量卸載到 TNIC 上的專用硬件中,這樣就沒必要將服務器資源消耗在對 TCP/IP幀的處理操做上,而是能夠將其用於知足應用程序和系統的其餘需求,從而提升了系統的總體性能。這彷佛是一種改進網絡性能的極好方案,但通用的 TCP卸載解決方案卻不斷地失敗, TOE只適合一些特定的應用環境。 例如,TCP卸載機制的適用上下文包括經過商用網絡硬件設備構建的存儲互連結構、高性能集羣解決方案等。
對千兆位以太網的工做負荷分析代表, 系統須要 1GHz的 CPU處理能力來處理每吉比特網絡流量。隨着更高速的處理器系統、高性能串行PCI-Express系統總線、內置了檢驗和運算邏輯的以太網控制器以及中斷縮減機制的出現,用戶將能夠在服務器中使用多條千兆位以太網鏈接,同時不會致使性能降低。然而,網絡帶寬的改善也與系統經過諸如TOE之類的解決方案來提升網絡性能的其餘部件改進保持一致。但因爲存在着嚴重的性能問題,而且實際部署 TCP卸載機制比較複雜,TCP卸載做爲一種通用解決方案已經失敗。學術界和產業界中對於 TOE技術都存在着支持與反對的聲音。然而,除了集羣和網絡存儲解決方案外,許多廠商還開發了用於其餘各類工做負荷的 TNIC。
與 LinuxTCP/IP軟件棧代碼相比,各類 TOE解決方案都是專有的,其功能也各異。這些專有的 TOE方案中可能不提供某些特性如 IPCHAINS、 IPTABLES以及通用報文處理能力。許多開發 TNIC和驅動程序的廠商都支持多種操做系統。儘管早期測試結果顯示在Linux上 NetBench的性能改進了 17%, 但所用的驅動程序在測試時並不穩定, 所以須要進一步研究這種特性。若是驅動程序和 NIC更穩定的話,應該會實現更高的性能結果。
注意 TOE不一樣於 TCP分片卸載(TSO)。 TSO只對數據分片操做進行卸載。在 TSO技術中,TCP/IP棧將應用程序傳來的整個消息都封裝在幀裏傳遞給 NIC。 NIC再將數據(消息)劃分爲多個幀,爲每一個幀構造幀頭以便進行傳輸。這種卸載操做只在發送端(輸出通訊)完成,不處理輸入通訊。而 TOE將整個 TCP/IP協議棧處理操做都卸載到 NIC上,包括輸入和輸出處理。
儘管TOE解決方案是一種改進網絡性能的急需技術, 但目前還不清楚 Linux開源社區將如何採納該技術。有些人認爲 LinuxTCP/IP棧中已支持 Zerocopy機制, 所以複製操做的次數已獲得減小。採用 TOE技術所實現的多數性能收益可經過 NIC中的校驗和、分片卸載以及中斷縮減機制來獲取,而其他功能只執行基本的 socket管理和進程喚醒,所以不須要這種技術。若是 TOE解決方案不斷改進, 而且與軟件網絡棧相比可以顯示出巨大優點,則 TOE技術的採用量可能會增長。
目前,只有商業公司在開發 TOE引擎, 所以這類解決方案的實現隨着廠商的不一樣而各異。廠商也許可以減小或解決 TOE實現和部署中的難題, 並改變那些不肯意認可 TOE是網絡性能改進可行方案的懷疑者的想法。
3、 示例分析
下面給出該示例分析所使用的基準測試的結果,並展現目前爲止所討論的各類性能加強特性的累積性能改進。某些基準測試捕獲全部特性的累積收益,而另外一些則捕獲特定工做負荷的特定收益。
一、 NetBench
下圖所示爲 Linux內核與 Samba的各類加強和調優機制給 NetBench基準程序吞吐率帶來的性能改進。這些測試的硬件執行環境是由 4個 1.5GHz P4處理器、 4個千兆位以太網適配器、 2GB內存以及 14個 15krpm SCSI磁盤構成的 Pentium 4系統。 全部測試都使用 SUSE 8.0版本。 每次後續測試都會包含一個新的內核、 調優或 Samba變化。全部測試都使用 Ziff-Davis的 NetBench Enterprise Disk Suite基準程序 。

下面描述了上圖中各列的名稱:
- 基準配置(Baseline)。表明了 SUSE Linux企業級服務器 8.0版本(SUSE SLES 8)的一個乾淨安裝,未對性能配置進行任何修改。
- data=writeback。 對一個 Ext3默認掛接選項的配置加以改動,將/data文件系統(提供了 Samba共享)從 ordered改成 writeback。這極大改進了文件系統在元數據密集的工做負荷下的性能,例如本例。
- smblog=1。Samba日誌級別從 2改成 1,以減小對 Samba日誌文件的磁盤 I/O操做。級別1足以將關鍵錯誤記入日誌中。
- SendFile/Zerocopy。 該補丁使得 Samba對於客戶讀請求使用 SendFile機制。該補丁與 Linux的 Zerocopy技術(最先出現於 2.4.4版本中)結合使用,能夠消除兩種高開銷的內存複製操做。
- O(1)調度器。 這個小改進有利於將來的其餘性能改進。 O(1)調度器是可以改進對稱多處理器性能的多隊列調度器。這是 Linux 2.5和 2.6內核中的默認調度器。
- 均等親合的 IRQ(evenly affined IRQ)。 4個網絡適配器中每一個適配器的中斷都由惟一的處理器來處理。在 P4體系結構中,SUSE SLES 8的 IRQ至 CPU映射機制默認爲輪詢分配(destination= irq_num% num_cpus)。在示例中,網絡適配器的全部 IRQ都被轉至 CPU0。 這對於性能很是有益, 由於該代碼上的 cache暖和性已得到改進, 但隨着更多 NIC被添加到系統中, 單個 CPU可能難以處理所有網絡負荷。理想的解決方案是均勻地親合這些 IRQ, 使得每一個處理器都處理來自一個 NIC的中斷。這種機制與進程親合性結合使用,應該可以將指派給某個特定 NIC上的進程也指派到一個 CPU上,以便獲取最高性能。
- 進程親合性。 該技術確保對於每一個被處理的網絡中斷,相應的 smbd進程都在同一個 CPU上被調度以便進一步改善 cache暖和性。
這主要是一種基準測試技術,並不普遍用於其餘場合。若是能夠在邏輯上將工做負荷均勻劃分到多個 CPU上, 這將是一個很大的性能收益。現實中的大多數工做負荷都是動態的,所以沒法預先肯定親合性。
- /proc/sys/net/hl=763。 增長網絡協議棧代碼中擁有的緩衝區數量,從而使網絡棧不需調用內存系統來從中獲取或釋放緩衝區。 Linux 2.6內核中未提供這個調優特性。
- 實施大小寫敏感特性。 若是未實施這個特性, Samba在打開一個文件前可能須要搜索該文件的不一樣版本名稱, 由於同一個文件能夠擁有多個文件名組合。啓動大小寫敏感特性就能夠消除這些猜想。
- 自旋鎖(spinlock)。 Samba的數據庫中使用了高開銷的 fcntl()調用。可使用自旋鎖來代替這個調用。利用在 posix_lock_file()中發現的大內核鎖(Big Kernel Lock)可以減小大內核鎖的競爭和等待時間。要使用該特性, 能夠經過--use-spin-locks來配置Samba,以下例所示。
Smbd --use-spin-locks -p <port_number> -O<socket option>
-s <configuration file>
- dcache 讀複製更新(read copy update)。 經過使用讀複製更新技術,一種新的dlookup()實現能夠減小目錄項查詢次數。讀複製更新是 Linux中用做互斥機制的一種兩階段更新方法, 能夠避免自旋等待鎖的開銷。更多信息參見 Linux可伸縮性研究計劃(Linux Scalability Effort)中關於鎖(locking)技術方面的工做。
二、 Netperf3(千兆位以太網調優實例分析)
價格日益下降的千兆位以太網卡正快速取代百兆位以太網卡。當前,系統製造商在主板上提供了千兆位以太網支持, 系統供應商和集成商也選擇使用千兆位以太網卡和交換機來鏈接磁盤服務器、計算機中心以及部門骨幹網。下面討論 Linux操做系統中的千兆位網絡性能,以及千兆位以太網調優對網絡性能的改進。
千兆位以太網卡(Intel Gigabit Ethernet和 Acenic Gigabit Ethernet)提供了幾個有利於處理高吞吐率的額外特性。這些特性包括對巨型幀(MTU)長度、中斷延遲(interrupt-delay)以及TX/RX描述符的支持:
- 巨型幀長度。千兆位以太網卡的 MTU長度能夠大於 1500B。百兆位以太網中 1500B的 MTU限制再也不存在。增長 MTU的大小一般可以改進網絡吞吐率,但必須確保網絡路由器支持巨型幀長度。不然,當系統連入百兆位以太網絡時,千兆位以太網卡會降至百兆位的能力。
- 中斷延遲/中斷合併。能夠針對接收中斷和傳輸中斷設置中斷合併特性,使得 NIC在指定時間內延緩生成中斷。例如,當 RxInt設置爲 1.024μs(這是 Intel GigabitEthernet網卡上的默認值)時, NIC將收到的幀放入內存中, 在通過 1.024μs後才生成一箇中斷。這個特性減小了上下文切換次數,所以能夠改進 CPU效率,但它同時也增長了接收報文的延遲。若是針對網絡流量對中斷合併特性加以適當調優,也可以改進 CPU效率和網絡吞吐率性能。
- 傳輸和接收描述符。千兆位以太網驅動程序使用這些參數來分配數據發送和接收緩衝區。增長其取值能夠容許驅動程序緩衝更多的輸入報文。每一個描述符都包含一個傳輸和接收描述符緩衝區以及一個數據緩衝區。這個數據緩衝區的大小依賴於MTU長度。對於本例的驅動程序, MTU最大長度爲 16110。
關於千兆位以太網的其餘研究也代表,系統大約須要 1GHz的 CPU處理能力來處理每千兆位網絡流量。筆者的實驗也證明了這一點。 但添加更多數量的 GHz處理器和千兆位以太網卡並不會相應地提升網絡吞吐率,即便在 GHz處理器數目等於千兆位以太網卡數量的狀況下。在 SMP處理器上, 其餘瓶頸如系統總線會影響到千兆位以太網卡的可伸縮性。 NIC測試代表, 4個網卡中只有 3個網卡能夠達到通訊介質速度。
在一臺主頻爲1.6GHz的4路Pentium 4機器與4臺客戶機(主頻爲1.0GHz的Pentium3)之間執行這些測試,這些機器擁有可達到通訊介質速度上限的千兆位網卡。全部機器都使用 Linux 2.4.17 SMP vanilla內核。 e1000驅動程序的版本號是 4.1.7。測試類型是Netperf3的 PACKET_STREAM和 PACKET_MAERTS,其 MTU都是 1500B。 Pentium 4
機器擁有 16GB RAM和 4個 CPU。4個 NIC均等分佈在 100MHz和 133MHz PCI-X插槽之間。在Pentium 4系統上禁用了超線程特性。
PACKET_STREAM測試只傳輸沒有任何 TCP/IP報文頭部的原始數據。它不經過TCP/IP協議層次來傳輸或接收報文,只是爲了測試 CPU、 內存、 PCI 總線和 NIC驅動程序以查找這些部件中的瓶頸。它使用不一樣值來調優千兆位驅動程序的中斷延遲以及傳輸和接收描述符,以肯定這些參數針對環境的最佳取值。另外一個調優選項是改變 socket緩衝區容量。
以下表所示,在這 4個網卡中,可達到的最大吞吐率是 2808Mbps,實現該吞吐率的調優參數設置以下: 傳輸和接收描述符數量爲 4096, 接收端和發送端的中斷延遲都爲 64, socket緩衝區大小約爲 132 000 。