poll與epoll

來源:互聯網
上載者:User

隨著2.6核心對epoll的完全支援,網路上很多的文章和範例程式碼都提供了這樣一個資訊:使用epoll代替傳統的poll能給網路服務應用帶來效能上
的提升。但大多文章裡關於效能提升的原因解釋的較少,這裡我將試分析一下核心(2.6.21.1)代碼中poll與epoll的工作原理,然後再通過一些
測試資料來對比具體效果。

       POLL:

       先說poll,poll或select為大部分Unix/Linux程式員所熟悉,這倆個東西原理類似,效能上也不存在明顯差異,但select對所監控的檔案描述符數量有限制,所以這裡選用poll做說明。
   
       poll是一個系統調用,其核心入口函數為sys_poll,sys_poll幾乎不做任何處理直接調用do_sys_poll,do_sys_poll的執行過程可以分為三個部分:

       1,將使用者傳入的pollfd數組拷貝到核心空間,因為拷貝操作和數組長度相關,時間上這是一個O(n)操作,這一步的代碼在do_sys_poll中包括從函數開始到調用do_poll前的部分。

   
  
2,查詢每個檔案描述符對應裝置的狀態,如果該裝置尚未就緒,則在該裝置的等待隊列中加入一項並繼續查詢下一裝置的狀態。查詢完所有裝置後如果沒有一個設
備就緒,這時則需要掛起當前進程等待,直到裝置就緒或者逾時,掛起操作是通過調用schedule_timeout執行的。裝置就緒後進程被通知繼續運
行,這時再次遍曆所有裝置,以尋找就緒裝置。這一步因為兩次遍曆所有裝置,時間複雜度也是O(n),這裡面不包括等待時間。相關代碼在do_poll函數
中。

       3,將獲得的資料傳送到使用者空間並執行釋放記憶體和剝離等待隊列等善後工作,向使用者空間拷貝資料與剝離等待隊列等操作的的時間複雜度同樣是O(n),具體程式碼封裝括do_sys_poll函數中調用do_poll後到結束的部分。

       EPOLL:

       接下來分析epoll,與poll/select不同,epoll不再是一個單獨的系統調用,而是由epoll_create/epoll_ctl/epoll_wait三個系統調用組成,後面將會看到這樣做的好處。

       先來看sys_epoll_create(epoll_create對應的核心功能),這個函數主要是做一些準備工作,比如建立資料結構,初始化資料並最終返回一個檔案描述符(表示新建立的虛擬epoll檔案),這個操作可以認為是一個固定時間的操作。

        epoll是做為一個虛擬檔案系統來實現的,這樣做至少有以下兩個好處:

        1,可以在核心裡維護一些資訊,這些資訊在多次epoll_wait間是保持的,比如所有受監控的檔案描述符。

        2, epoll本身也可以被poll/epoll;

       具體epoll的虛擬檔案系統的實現和效能分析無關,不再贅述。

       在sys_epoll_create中還能看到一個細節,就是epoll_create的參數size在現階段是沒有意義的,只要大於零就行。

   
  
接著是sys_epoll_ctl(epoll_ctl對應的核心功能),需要明確的是每次調用sys_epoll_ctl只處理一個檔案描述符,這裡主
要描述當op為EPOLL_CTL_ADD時的執行過程,sys_epoll_ctl做一些安全性檢查後進入ep_insert,ep_insert裡將
ep_poll_callback做為回掉函數加入裝置的等待隊列(假定這時裝置尚未就緒),由於每次poll_ctl只操作一個檔案描述符,因此也可以
認為這是一個O(1)操作

        ep_poll_callback函數很關鍵,它在所等待的裝置就緒後被系統回掉,執行兩個操作:

       1,將就緒裝置加入就緒隊列,這一步避免了像poll那樣在裝置就緒後再次輪詢所有裝置找就緒者,降低了時間複雜度,由O(n)到O(1);
   
       2,喚醒虛擬epoll檔案;

   
  
最後是sys_epoll_wait,這裡實際執行操作的是ep_poll函數。該函數等待將進程自身插入虛擬epoll檔案的等待隊列,直到被喚醒(見
上面ep_poll_callback函數描述),最後執行ep_events_transfer將結果拷貝到使用者空間。由於只拷貝就緒裝置資訊,所以這
裡的拷貝是一個O(1)操作。

       還有一個讓人關心的問題就是epoll對EPOLLET的處理,即邊沿觸發的處理,粗略看代碼就是把一部分水平觸發模式下核心做的工作交給使用者來處理,直覺上不會對效能有太大影響,感興趣的朋友歡迎討論。

       POLL/EPOLL對比:

   
  
表面上poll的過程可以看作是由一次epoll_create/若干次epoll_ctl/一次epoll_wait/一次close等系統調用構成,
實際上epoll將poll分成若干部分實現的原因正是因為伺服器軟體中使用poll的特點(比如Web伺服器):

       1,需要同時poll大量檔案描述符;

       2,每次poll完成後就緒的檔案描述符只佔所有被poll的描述符的很少一部分。

       3,前後多次poll調用對檔案描述符數組(ufds)的修改只是很小;

       傳統的poll函數相當於每次調用都重起爐灶,從使用者空間完整讀入ufds,完成後再次完全拷貝到使用者空間,另外每次poll都需要對所有裝置做至少做一次加入和刪除等待隊列操作,這些都是低效的原因。

   
   
epoll將以上情況都細化考慮,不需要每次都完整讀入輸出ufds,只需使用epoll_ctl調整其中一小部分,不需要每次epoll_wait都執
行一次加入刪除等待隊列操作,另外改進後的機制使的不必在某個裝置就緒後搜尋整個裝置數組進行尋找,這些都能提高效率。另外最明顯的一點,從使用者的使用來
說,使用epoll不必每次都輪詢所有返回結果已找出其中的就緒部分,O(n)變O(1),對效能也提高不少。

       此外這裡還發現一點,是不是將epoll_ctl改成一次可以處理多個fd(像semctl那樣)會提高些許效能呢?特別是在假設系統調用比較耗時的基礎上。不過關於系統調用的耗時問題還會在以後分析。

       POLL/EPOLL測試資料對比

   
  
測試的環境:我寫了三段代碼來分別類比伺服器,活動的用戶端,僵死的用戶端,伺服器運行於一個自編譯的標準2.6.11核心系統上,硬體為
PIII933,兩個用戶端各自運行在另外的PC上,這兩台PC比伺服器的硬體效能要好,主要是保證能輕易讓伺服器滿載,三台機器間使用一個100M交換
機串連。

       伺服器接受並poll所有串連,如果有request到達則回複一個response,然後繼續poll。

       活動的用戶端(Active Client)類比若干並發的活動串連,這些串連不間斷的發送請求接受回複。

       僵死的用戶端(zombie)類比一些只串連但不發送請求的用戶端,其目的只是佔用伺服器的poll描述符資源。

        測試過程:保持10個並發活動串連,不斷的調整僵並發串連數,記錄在不同比例下使用poll與epoll的效能差別。僵死並發串連數根據比例分別是:0,10,20,40,80,160,320,640,1280,2560,5120,10240。

      
中橫軸表示僵死並發串連與活動並發串連之比,縱軸表示完成40000次請求回複所花費的時間,以秒為單位。紅色線條表示poll資料,綠色表示
epoll資料。可以看出,poll在所監控的檔案描述符數量增加時,其耗時呈線性增長,而epoll則維持了一個平穩的狀態,幾乎不受描述符個數影響。

       在監控的所有用戶端都是活動時,poll的效率會略高於epoll(主要在原點附近,即僵死並發串連為0時,圖上不易看出來),究竟epoll實現比poll複雜,監控少量描述符並非它的長處。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.