Windows五種IO模型效能分析

來源:互聯網
上載者:User

重疊I/O模型的另外幾個優點在於,微軟針對重疊I/O模型提供了一些特有的擴充函數。當使用重疊I/O模型時,可以選擇使用不同的完成通知方式。 

採用事件對象通知的重疊I/O模型是不可伸縮的,因為針對發出WSAWaitForMultipleEvents調用的每個線程,該I/O模型一次最多都只能支援6 4個通訊端。假如想讓這個模型同時管理不止64個通訊端,必須建立額外的工作者線程,以便等待更多的事件對象。因為作業系統同時能夠處理的事件對象是有限的,所以基於事件對象的I/O模型不具備伸縮性。 
使用完成常式通知的重疊I/O模型,因為以下幾個原因,也不是開發高效能伺服器的最佳選擇。首先,許多擴充功能不允許使用APC(Asyncroneus Procedure Call,非同步程序呼叫)完成通知。其次,由於APC在系統內部特有的處理機制,應用程式線程可能無限等待而得不到完成通知。當一個線程處於“可警告狀態”時,所有掛起的APC按照先進先出的順序(FIFO)接受處理。現在考慮這樣一種情況,伺服器已經建立起了一個串連,並且調用含有完成常式指標的WSARecv投遞了一個重疊I/O請求。當有資料到達時(即I/O完成時),完成常式執行並且再次調用WSARecv拋出另外一個重疊I/O請求。一個APC拋出的I/O操作需要一定的時間才能完成,所以這期間可能另外一個完成常式等待執行(比如本次WSARecv還沒接收完時,又有一個新的客戶接入並發來資料),因為還有更多的資料需要讀取(上一個客戶發來的資料尚未讀完)。只要(投遞WSARecv的)那個通訊端上還有“未決”(未接收完)的資料,就會導致調用線程長久阻塞。 
基於完成連接埠通知的重疊I/O模型是Windows NT系統提供的一個真正支援高伸縮性的I/O模型。在上一章中,探討了Winsock幾種常見的I/O模型,並且說明了當應對大規模客戶串連時,完成連接埠是最佳的選擇,因為它提供了最好的伸縮性。 
對不同Winsock I/O模型的效能測試結果如圖1所示。其中伺服器採用Pentium 4 1.7 GHz Xeon的CPU,768M記憶體;用戶端有3台PC,配置分別是Pentium 2 233MHz ,128 MB 記憶體,Pentium 2 350 MHz ,128 MB記憶體,Itanium 733 MHz ,1 GB記憶體。伺服器、用戶端安裝的作業系統都是Windows XP。

圖1 不同I/O模型的效能比較 

1.分析圖表1提供的測試結果可知,在所用的I/O模型中,阻塞模式效能最差。這個測試程式中,伺服器為每個客戶建立兩個線程:一個負責處理資料的接收,一個負責處理資料的發送。在多次測試中的共同問題就是,阻塞模式難以應對大規模的客戶串連,因為它在建立線程上耗費了太多的系統資源。因此,伺服器建立太多的線程後,再調用CreateThread函數時,將返回ERROR_NOT_ENOUGH_MEMORY的錯誤,這個錯誤碼提示記憶體不夠。那些發出串連請求的客戶則收到WSAECONNREFUSED的錯誤提示,表示串連的嘗試被拒絕。 
讓我們來看看監聽函數listen,其原型如下: 
WINSOCK_API_LINKAGE int WSAAPI listen(SOCKET s, int backlog ); 
參數一s已綁定了地址的監聽通訊端。 
參數二backlog指定了正在等待串連的最大隊列長度。 
參數backdog非常重要, 因為完全可能同時出現幾個對伺服器的串連請求。例如,假定backlog參數為2時有三個客戶機同時發出串連請求,那麼前兩個會被放在一個“等待處理”隊列中,以便應用程式依次為它們提供服務。而第三個串連的請求就會造成一個WSAECONNREFUSED錯誤。一旦伺服器接受了一個串連請求,那個串連請求就會從隊列中刪去,以便可以繼續接收其他客戶發出的串連請求。即當一個串連請求到來時隊列已滿,那麼客戶將收到一個WSAECONNREFUSED錯誤。而backlog參數本身的大小就存在著限制,這個限制是由協議提供者決定的。 
故阻塞模式下,由於系統資源的限制,其並發處理量是極難突破的。 


2.非阻塞模式表現出的效能要比阻塞模式稍好,但是佔用了太多的CPU處理時間。測試伺服器將所有客戶對應的socket分類放到FD_SET集合中,然後調用select函數篩選出對應集合中有事件發生的socket,並對集合更新。接下來調用FD_ISSET宏重新判斷一個通訊端是否在原來加入的FD_SET集合中。隨著客戶串連數量的增多,這種模型的局限性逐漸凸現。僅僅為了判斷一個通訊端是否有網路事件發生,就需要對集合FD_SET執行一次遍曆!使用迭代搜尋來對select更新的FD_SET進行掃描,效能可以得到一些提升。瓶頸在於,伺服器必須能夠很快地掃描出FD_SET集合中的有網路事件發生的通訊端的相關資訊。針對這個問題,可以使用更複雜的掃描演算法,如雜湊搜尋,它的效率是極高的。還需要注意的一個問題就是,非分頁池(即直接在實體記憶體中分配的記憶體)的使用極高。這是因為AFD(Ancillary Function Driver,由afd.sys提供的支援Windows Sockets應用程式的底層驅動程式,其中運行在核心模式下afd.sys驅動程式主要管理Winsock TCP/IP通訊)和TCP都將使用I/O緩衝,因為伺服器讀取資料的速度是有限的,相對於CPU的處理速度而言,I/O基本是零位元組的輸送量。 


3.基於Windows訊息機制的WSAAsyncSelect模型能夠處理一定的客戶串連量,但是擴充性也不是很好。因為訊息泵很快就會阻塞,降低了訊息處理的速度。在幾次測試中,伺服器只能處理大約1/3的用戶端串連。過多的用戶端串連請求都將返回錯誤提示碼WSAECONNREFUSED,說明伺服器不能及時處理FD_ACCEPT訊息導致串連失敗,這樣監聽隊列中待處理的串連請求不致於爆滿。然而,通過上表中的資料可以發現,對那些已經建立的串連,其平均輸送量也是極低的(即使對於那些對位元速率進行了限制的客戶也如此)。 


4.基於事件通知的WSAEventSelect模型表現得出奇的不錯。在所有的測試中,大多數時候,伺服器基本能夠處理所有的客戶串連,並且保持著較高的資料輸送量。這種模型的缺點是,每當有一個新串連時,需要動態管理線程池,因為每個線程只能夠等待64個事件對象。當客戶串連量超過64個後再有新客戶接入時,需要建立新的線程。在最後一次測試中,建立起了超過45,000個的客戶串連後,系統響應速度變得非常緩慢。這時由於為處理大規模的客戶串連建立了大量的線程,佔用了過多的系統資源。791個線程基本達到了極限,伺服器不能再接受更多的串連了,原因是WSAENOBUFS:無可用的緩衝區空間,通訊端無法建立。另外,用戶端程式也達到了極限,不能維持已經建立的串連。 
使用事件通知的重疊I/O模型和WSAEventSelect模型在伸縮性上差不多。這兩種模型都依賴於等待事件通知的線程池,處理客戶通訊時,大量線程內容相關的切換是它們共同的制約因素。重疊I/O模型和WSAEventSelect模型的測試結果很相似,都表現得不錯,直到線程數量超過極限。 


5.最後是針對基於完成連接埠通知的重疊I/O模型的效能測試,由上表中資料可以看出,它是所有I/O模型中效能最佳的。記憶體使用量率(包括使用者分頁池和非分頁池)和支援的客戶串連量與基於事件通知的重疊I/O模型和WSAEventSelect模型基本相同。真正不同的地方,在於對CPU的佔用。完成連接埠模型只佔用了60%的CPU,但是在維持同樣規模的串連量時,另外兩種模型(基於事件通知的重疊I/O模型和WSAEventSelect模型)佔用更多的CPU。完成連接埠的另外一個明顯的優勢是,它維持更大的輸送量。 
對以上各種模型進行分析後,可以會發現用戶端與伺服器資料通訊機制本身存在的缺陷是一個瓶頸。在以上測試中,伺服器被設計成只做簡單的回應,即只是將用戶端發送過來的資料發送回去。用戶端(即使有位元速度節流設定)不停的發送資料給伺服器,這導致大量資料阻塞在伺服器上與這個用戶端對應的通訊端上(無論是TCP緩衝區還是AFD的單通訊端緩衝區,它們都是在非分頁池上)。在最後三種效能比較好的模型中,同一時間只能執行一個接受輸入操作,這意味著在大多數時間,還是有很多資料處於“未決”狀態。可以修改伺服器程式使其以非同步方式接受資料,這樣一旦有資料達到,需要將資料緩衝起來。這種方案的缺點是,當一個客戶連續發送資料時,非同步接受到了大量的資料。這會導致其他的客戶無法接入,因為調用線程和工作者線程都不能處理其他的事件或完成通知。通常情況下,調用非阻塞非同步接收函數,先返回WSAEWOULDBLOCK,然後資料間斷性的傳輸,而不採取連續接收的方式。 
從以上測試結果,可以看出WSAEventSelect模型和重疊I/O模型是效能表現最佳的。兩種基於事件通知的模型中,建立線程池來等待事件完成通知並作後續處理是很繁瑣的,但是並不影響以它們來架構中型伺服器的良好效能。當線程的數量隨著用戶端串連數量而逐增時,CPU將花費大量時間線上程的環境切換上,這將影響伺服器的伸縮性,因為串連量達到一定數量後,便飽和了。完成連接埠模型提供了最佳的可擴充性,因為CPU使用率低,其支援的客戶串連量相對其他模型最多。 
I/O模型的選擇 
通過上一節對各種模型的測試分析,對於如何挑選最適合自己應用程式的I/O模型已經很明晰了。同開發一個簡單的運行多線程的鎖定模式應用相比,其他每種I/O模型都需要更為複雜的編程工作。因此,針對客戶機和伺服器應用開發模型的選擇,有以下原則。 
1. 用戶端 
若打算開發一個客戶機應用,令其同時管理一個或多個通訊端,那麼建議採用重疊I/O或WSAEventSelect模型,以便在一定程度上提升效能。然而,假如開發的是一個以Windows為基礎的應用程式,要進行視窗訊息的管理,那麼WSAAsyncSelect模型恐怕是一種最好的選擇,因為WSAAsyncSelect本身便是從Windows訊息模型借鑒來的。採用這種模型,程式需具備訊息處理功能。 
2. 伺服器端 
若開發的是一個伺服器應用,要在一個給定的時間,同時控制多個通訊端,建議採用重疊I/O模型,這同樣是從效能角度考慮的。但是,如果伺服器在任何給定的時間,都會為大量I/O請求提供服務,便應考慮使用I/O完成連接埠模型,從而獲得更佳的效能。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.