Linux下多路複用IO接口epoll/select/poll的區別

selectepoll效率差的原因:select是輪詢,epoll是觸發式的,所以效率高。

Select:

1.Socket數量限制:該模式可操作的Socket數由FD_SETSIZE決定,內核默認32*32=1024.

2.操作限制:通過遍歷FD_SETSIZE(1024)Socket來完成調度,不管哪個Socket是活躍的,都遍歷一遍.

Poll:

1.Socket數量幾乎無限制:該模式下的Socket對應的fd列表由一個數組來保存,大小不限(默認4k).

2.操作限制:Select.

Epoll:

1.Socket數量無限制:Poll

2.操作無限制:基於內核提供的反射模式,有活躍Socket,內核訪問該Socketcallback,不需要遍歷輪詢.但是當所有Socket都活躍的時候,這時候所有的callback都被喚醒,會導致資源的競爭.既然都是要處理所有的Socket,那麼遍歷是最簡單最有效的實現方式.

舉例來說:

      對於IM服務器,服務器和服務器之間都是長鏈接,但數量不多,一般一臺60\70,比如採用ICE這種架構設計,但請求相當頻繁和密集,這時候通過反射喚醒callback不一定比用select去遍歷處理更好.

       對於Web服務器,都是瀏覽器客戶端發起的http短鏈接請求,數量很大,好一點的網站動輒每分鐘上千個請求過來,同時服務器端還有更多的閒置等待超時的Socket,這時候沒必要把全部的Socket都遍歷處理,因爲那些等待超時的請求是大多數的,這樣用Epoll會更好.

支持一個進程打開大數目的socket描述符

       select 最不能忍受的是一個進程所打開的FD是有一定限制的,由FD_SETSIZE設置,默認值是1024。對於那些需要支持的上萬連接數目的IM服務器來說顯然太少了。這時候你一是可以選擇修改這個宏然後重新編譯內核,不過資料也同時指出這樣會帶來網絡效率的下降,二是可以選擇多進程的解決方案(傳統的 Apache方案),不過雖然linux上面創建進程的代價比較小,但仍舊是不可忽視的,加上進程間數據同步遠比不上線程間同步的高效,所以也不是一種完美的方案。不過 epoll則沒有這個限制,它所支持的FD上限是最大可以打開文件的數目,這個數字一般遠大於2048,舉個例子,在1GB內存的機器上大約是10萬左右,具體數目可以cat /proc/sys/fs/file-max察看,一般來說這個數目和系統內存關係很大。

IO效率不隨FD數目增加而線性下降

       傳統的select/poll另一個致命弱點就是當你擁有一個很大的socket集合,不過由於網絡延時,任一時間只有部分的socket是“活躍”的,但是select/poll每次調用都會線性掃描全部的集合,導致效率呈現線性下降。但是epoll不存在這個問題,它只會對“活躍”的socket進行操作---這是因爲在內核實現中epoll是根據每個fd上面的callback函數實現的。那麼,只有“活躍”的socket纔會主動的去調用 callback函數,其他idle狀態socket則不會,在這點上,epoll實現了一個“僞”AIO,因爲這時候推動力在os內核。在一些 benchmark中,如果所有的socket基本上都是活躍的---比如一個高速LAN環境,epoll並不比select/poll有什麼效率,相反,如果過多使用epoll_ctl,效率相比還有稍微的下降。但是一旦使用idle connections模擬WAN環境,epoll的效率就遠在select/poll之上了。

select模式低效的原因

       select 模式低效是由select的定義所決定的,與操作系統實現無關,任何內核在實現select時必須做輪循,才能知道這些socket的情況,這是會消耗 cpu的。此外,當你擁有一個很大socket集的時候,儘管任一時間只有小部分的socket"活躍"的,但每次你都不得不將所有的socket填入到一個FD_SET中,這也會消耗一些cpu,並且當select返回後,處理業務時你可能還需要做“上下文映射”,同樣也會有一些性能影響,因此 selectepoll相對低效。

epoll的適用情景就是大量的socket,但是活躍多不是很高的情況。



轉自:http://www.cppentry.com/bencandy.php?fid-54-id-1129-page-1.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章