epoll比select高效的原因及select比epoll高效場景

epoll高效的原因,從下面幾個方向來說:

  1. 用戶態將文件描述符傳入內核的方式

select:
select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

根據API,可以看出select需要提供三個文件描述符(內部是位圖,所以只用三個即可),分別監聽讀、寫、異常。

epoll:

epoll_create的時候在內核高速cache中建紅黑樹以及就緒鏈表(存儲已有監聽事件到達的fd)。用戶執行epoll_ctl的時候就會在紅黑樹中增加相應的節點。

  1. 內核監測文件描述符是否可讀可寫的方式

select:

採取輪詢的方式,遍歷fd,最後返回一個描述符讀寫操作是否就緒的mask掩碼,根據這個掩碼給fd_set賦值。

epoll:

通過在epoll_ctl的時候想內核註冊回調函數,內核在監測到文件描述符可讀/可寫的時候調用相應的回調,將文件描述符相關的結構體放入就緒鏈表中。

  1. 如何找到就緒的文件描述符並傳遞給用戶

select:

用戶並不知道哪些文件描述符處於就緒狀態,需要遍歷。

epoll:

epoll_wait的時候直接檢查就緒鏈表,返回的fd都是已經就緒的,以此處理即可。

  1. 繼續重新監聽時如何重複以上步驟

select:

將新的文件描述符重新傳入內核態中,需要重新複製一次。

epoll:

無須重新傳入,直接沿用紅黑樹中節點即可。

  1. 在什麼情況下select會比epoll高效呢

在少連接高併發的情況下。

因爲,連接少意味着不會超過select1024的上限,高併發意味着一次wait每一個連接都會來數據。把掃描有事件連接時的O(n)的複雜度降至O(1)。

加上每次只需要複製4次fd_set從內核空間和用戶空間往返,(sizeof(fd_set)=128),總體上比epoll要複製的量要少(sizeof(struct epoll_event)=12)(假設100個連接 12*100=1200)。在這種情況下select是要比epoll高效的。

到這裏延伸一下,如果select支持大量連接,並且每一個連接都是相當活躍的,即還是O(n)->O(1)的情況。那麼select的性能要比epoll高。

也就是說select的差距主要體現在每次內核O(n)的去遍歷fd,用戶也需要去遍歷fd,造成效率低下。

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