• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            網(wǎng)絡(luò)服務(wù)器軟件開發(fā)/中間件開發(fā),關(guān)注ACE/ICE/boost

            C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
              152 Posts :: 3 Stories :: 172 Comments :: 0 Trackbacks
            2007-06-30 23:58
            隨著2.6內(nèi)核對epoll的完全支持,網(wǎng)絡(luò)上很多的文章和示例代碼都提供了這樣一個信息:使用epoll代替?zhèn)鹘y(tǒng)的poll能給網(wǎng)絡(luò)服務(wù)應(yīng)用帶來性能上 的提升。但大多文章里關(guān)于性能提升的原因解釋的較少,這里我將試分析一下內(nèi)核(2.6.21.1)代碼中poll與epoll的工作原理,然后再通過一些 測試數(shù)據(jù)來對比具體效果。

               POLL:

               先說poll,poll或select為大部分Unix/Linux程序員所熟悉,這倆個東西原理類似,性能上也不存在明顯差異,但select對所監(jiān)控的文件描述符數(shù)量有限制,所以這里選用poll做說明。

               poll是一個系統(tǒng)調(diào)用,其內(nèi)核入口函數(shù)為sys_poll,sys_poll幾乎不做任何處理直接調(diào)用do_sys_poll,do_sys_poll的執(zhí)行過程可以分為三個部分:

               1,將用戶傳入的pollfd數(shù)組拷貝到內(nèi)核空間,因為拷貝操作和數(shù)組長度相關(guān),時間上這是一個O(n)操作,這一步的代碼在do_sys_poll中包括從函數(shù)開始到調(diào)用do_poll前的部分。

               2,查詢每個文件描述符對應(yīng)設(shè)備的狀態(tài),如果該設(shè)備尚未就緒,則在該設(shè)備的等待隊列中加入一項并繼續(xù)查詢下一設(shè)備的狀態(tài)。查詢完所有設(shè)備后如果沒有一個設(shè) 備就緒,這時則需要掛起當(dāng)前進(jìn)程等待,直到設(shè)備就緒或者超時,掛起操作是通過調(diào)用schedule_timeout執(zhí)行的。設(shè)備就緒后進(jìn)程被通知繼續(xù)運 行,這時再次遍歷所有設(shè)備,以查找就緒設(shè)備。這一步因為兩次遍歷所有設(shè)備,時間復(fù)雜度也是O(n),這里面不包括等待時間。相關(guān)代碼在do_poll函數(shù) 中。

               3,將獲得的數(shù)據(jù)傳送到用戶空間并執(zhí)行釋放內(nèi)存和剝離等待隊列等善后工作,向用戶空間拷貝數(shù)據(jù)與剝離等待隊列等操作的的時間復(fù)雜度同樣是O(n),具體代碼包括do_sys_poll函數(shù)中調(diào)用do_poll后到結(jié)束的部分。

               EPOLL:

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

               先來看sys_epoll_create(epoll_create對應(yīng)的內(nèi)核函數(shù)),這個函數(shù)主要是做一些準(zhǔn)備工作,比如創(chuàng)建數(shù)據(jù)結(jié)構(gòu),初始化數(shù)據(jù)并最終返回一個文件描述符(表示新創(chuàng)建的虛擬epoll文件),這個操作可以認(rèn)為是一個固定時間的操作。

                   epoll是做為一個虛擬文件系統(tǒng)來實現(xiàn)的,這樣做至少有以下兩個好處:

                   1,可以在內(nèi)核里維護(hù)一些信息,這些信息在多次epoll_wait間是保持的,比如所有受監(jiān)控的文件描述符。

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

               具體epoll的虛擬文件系統(tǒng)的實現(xiàn)和性能分析無關(guān),不再贅述。

               在sys_epoll_create中還能看到一個細(xì)節(jié),就是epoll_create的參數(shù)size在現(xiàn)階段是沒有意義的,只要大于零就行。

               接著是sys_epoll_ctl(epoll_ctl對應(yīng)的內(nèi)核函數(shù)),需要明確的是每次調(diào)用sys_epoll_ctl只處理一個文件描述符,這里主 要描述當(dāng)op為EPOLL_CTL_ADD時的執(zhí)行過程,sys_epoll_ctl做一些安全性檢查后進(jìn)入ep_insert,ep_insert里將 ep_poll_callback做為回掉函數(shù)加入設(shè)備的等待隊列(假定這時設(shè)備尚未就緒),由于每次poll_ctl只操作一個文件描述符,因此也可以 認(rèn)為這是一個O(1)操作

                   ep_poll_callback函數(shù)很關(guān)鍵,它在所等待的設(shè)備就緒后被系統(tǒng)回掉,執(zhí)行兩個操作:

               1,將就緒設(shè)備加入就緒隊列,這一步避免了像poll那樣在設(shè)備就緒后再次輪詢所有設(shè)備找就緒者,降低了時間復(fù)雜度,由O(n)到O(1);

               2,喚醒虛擬的epoll文件;

               最后是sys_epoll_wait,這里實際執(zhí)行操作的是ep_poll函數(shù)。該函數(shù)等待將進(jìn)程自身插入虛擬epoll文件的等待隊列,直到被喚醒(見 上面ep_poll_callback函數(shù)描述),最后執(zhí)行ep_events_transfer將結(jié)果拷貝到用戶空間。由于只拷貝就緒設(shè)備信息,所以這 里的拷貝是一個O(1)操作。

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

               POLL/EPOLL對比:

               表面上poll的過程可以看作是由一次epoll_create/若干次epoll_ctl/一次epoll_wait/一次close等系統(tǒng)調(diào)用構(gòu)成, 實際上epoll將poll分成若干部分實現(xiàn)的原因正是因為服務(wù)器軟件中使用poll的特點(比如Web服務(wù)器):

               1,需要同時poll大量文件描述符;

               2,每次poll完成后就緒的文件描述符只占所有被poll的描述符的很少一部分。

               3,前后多次poll調(diào)用對文件描述符數(shù)組(ufds)的修改只是很小;

               傳統(tǒng)的poll函數(shù)相當(dāng)于每次調(diào)用都重起爐灶,從用戶空間完整讀入ufds,完成后再次完全拷貝到用戶空間,另外每次poll都需要對所有設(shè)備做至少做一次加入和刪除等待隊列操作,這些都是低效的原因。

                   epoll將以上情況都細(xì)化考慮,不需要每次都完整讀入輸出ufds,只需使用epoll_ctl調(diào)整其中一小部分,不需要每次 epoll_wait都執(zhí)行一次加入刪除等待隊列操作,另外改進(jìn)后的機制使的不必在某個設(shè)備就緒后搜索整個設(shè)備數(shù)組進(jìn)行查找,這些都能提高效率。另外最明 顯的一點,從用戶的使用來說,使用epoll不必每次都輪詢所有返回結(jié)果已找出其中的就緒部分,O(n)變O(1),對性能也提高不少。

               此外這里還發(fā)現(xiàn)一點,是不是將epoll_ctl改成一次可以處理多個fd(像semctl那樣)會提高些許性能呢?特別是在假設(shè)系統(tǒng)調(diào)用比較耗時的基礎(chǔ)上。不過關(guān)于系統(tǒng)調(diào)用的耗時問題還會在以后分析。

               POLL/EPOLL測試數(shù)據(jù)對比:

               測試的環(huán)境:我寫了三段代碼來分別模擬服務(wù)器,活動的客戶端,僵死的客戶端,服務(wù)器運行于一個自編譯的標(biāo)準(zhǔn)2.6.11內(nèi)核系統(tǒng)上,硬件為 PIII933,兩個客戶端各自運行在另外的PC上,這兩臺PC比服務(wù)器的硬件性能要好,主要是保證能輕易讓服務(wù)器滿載,三臺機器間使用一個100M交換 機連接。

               服務(wù)器接受并poll所有連接,如果有request到達(dá)則回復(fù)一個response,然后繼續(xù)poll。

               活動的客戶端(Active Client)模擬若干并發(fā)的活動連接,這些連接不間斷的發(fā)送請求接受回復(fù)。

               僵死的客戶端(zombie)模擬一些只連接但不發(fā)送請求的客戶端,其目的只是占用服務(wù)器的poll描述符資源。

                   測試過程:保持10個并發(fā)活動連接,不斷的調(diào)整僵并發(fā)連接數(shù),記錄在不同比例下使用poll與epoll的性能差別。僵死并發(fā)連接數(shù)根據(jù)比例分別是:0,10,20,40,80,160,320,640,1280,2560,5120,10240。

               下圖中橫軸表示僵死并發(fā)連接與活動并發(fā)連接之比,縱軸表示完成40000次請求回復(fù)所花費的時間,以秒為單位。紅色線條表示poll數(shù)據(jù),綠色表示 epoll數(shù)據(jù)。可以看出,poll在所監(jiān)控的文件描述符數(shù)量增加時,其耗時呈線性增長,而epoll則維持了一個平穩(wěn)的狀態(tài),幾乎不受描述符個數(shù)影響。

               在監(jiān)控的所有客戶端都是活動時,poll的效率會略高于epoll(主要在原點附近,即僵死并發(fā)連接為0時,圖上不易看出來),究竟epoll實現(xiàn)比poll復(fù)雜,監(jiān)控少量描述符并非它的長
            posted on 2008-06-01 22:15 true 閱讀(1655) 評論(0)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)服務(wù)器開發(fā)linux
            91精品国产91久久| 欧美黑人又粗又大久久久| 看久久久久久a级毛片| 久久最新免费视频| 欧美久久久久久午夜精品| 国内精品久久久久影院网站| 久久亚洲欧美日本精品| 国内精品久久久久影院免费| 久久精品国产亚洲欧美| 青青热久久综合网伊人| 四虎国产精品免费久久5151| 色综合久久天天综合| 久久久99精品成人片中文字幕| 久久久久黑人强伦姧人妻| 久久精品这里只有精99品| 日韩中文久久| 亚洲色欲久久久综合网东京热| 久久精品人成免费| 色综合久久精品中文字幕首页| 国产精品一区二区久久精品无码| 欧美亚洲另类久久综合婷婷| 久久久久精品国产亚洲AV无码| 久久久久亚洲AV无码麻豆| 久久精品国产一区二区三区日韩| 国产精品欧美久久久久无广告| 欧美日韩精品久久久免费观看 | 青青热久久国产久精品| 久久人妻AV中文字幕| 成人免费网站久久久| 青青久久精品国产免费看| 中文字幕日本人妻久久久免费 | 亚洲精品无码专区久久久| 国产精品久久久久国产A级| 久久成人国产精品一区二区| 中文国产成人精品久久不卡| 亚洲国产成人久久综合碰碰动漫3d | 亚洲综合熟女久久久30p| 26uuu久久五月天| 亚洲精品高清国产一线久久| 久久艹国产| 欧美伊香蕉久久综合类网站|