網絡庫libevent、libev、libuv對比
Libevent、libev、libuv三個網絡庫,都是c語言實現的異步事件庫Asynchronousevent library)。
異步事件庫本質上是提供異步事件通知(Asynchronous Event Notification,AEN)的。異步事件通知機制就是根據發生的事件,調用相應的回調函數進行處理。
事件(Event):事件是異步事件通知機制的核心,比如fd事件、超時事件、信號事件、定時器事件。有時候也稱事件為事件處理器(EventHandler),這個名稱更形象,因為Handler本身表示了包含處理所需數據(或數據的地址)和處理的方法(回調函數),更像是面向對象思想中的稱謂。
事件循環(EventLoop):
對於應用程序來說,這些只是異步事件庫提供的API,封裝了異步事件庫跟操作系統的交互,異步事件庫會選擇一種操作系統提供的機制來實現某一種事件,比如利用Unix/Linux平臺的epoll機制實現網絡IO事件,在同時存在多種機制可以利用時,異步事件庫會采用最優機制。
對比下三個庫:
libevent :名氣最大,應用最廣泛,歷史悠久的跨平臺事件庫;
libev :較libevent而言,設計更簡練,性能更好,但對Windows支持不夠好;
libuv :開發node的過程中需要一個跨平臺的事件庫,他們首選了libev,但又要支持Windows,故重新封裝了一套,linux下用libev實現,Windows下用IOCP實現;
在github上的影響力:
可見,目前libuv的影響力最大,其次是libevent,libev關註的人較少。
優先級、事件循環、線程安全維度的對比
特性 |
libevent |
libev |
libuv |
優先級 |
激活的事件組織在優先級隊列中,各類事 件默認的優先級是相同的,可以通過設置 事件的優先級使其優先被處理 |
也是通過優先級隊列來管理激活的時間, 也可以設置事件優先級 |
沒有優先級概念,按照固定的順序訪 問各類事件 |
事件循環 |
event_base用於管理事件 |
激活的事件組織在優先級隊列中,各類事件默認的優先級是相同的, 可以通 過設置事件的優先級 使其優先被處理 |
|
線程安全 |
event_base和loop都不是線程安全的,一個event_base或loop實例只能在用戶的一個線程內訪問(一般是主線程),註冊到event_base或者loop的event都是串行訪問的,即每個執行過程中,會按照優先級順序訪問已經激活的事件,執行其回調函數。所以在僅使用一個event_base或loop的情況下,回調函數的執行不存在並行關系
|
事件種類
type |
libevent |
libev |
libuv |
IO |
fd |
io |
fs_event |
計時器(mono clock) |
timer |
timer |
timter |
計時器(wall clock) |
-- |
periodic |
-- |
信號 |
signal |
signal |
signal |
進程控制 |
-- |
child |
process |
文件stat |
-- |
stat |
fs_poll |
每次循環都會執行的Idle事件 |
-- |
idle |
idle |
循環block之前執行 |
-- |
prepare |
prepare |
循環blcck之後執行 |
-- |
check |
check |
嵌套loop |
-- |
embed |
-- |
fork |
-- |
fork |
-- |
loop銷毀之前的清理工作 |
-- |
cleanup |
-- |
操作另一個線程中的loop |
-- |
async |
async |
stream ( tcp, pipe, tty ) |
stream ( tcp, pipe, tty ) |
stream ( tcp, pipe, tty ) |
stream ( tcp, pipe, tty ) |
這個對比對於libev和libuv更有意義,對於libevent,很多都是跟其設計思想有關的。 libev中的embed很少用,libuv沒有也沒關系;cleanup完全可以用libuv中的async_exit來替代;libuv沒有fork事件。
可移植性
三個庫都支持Linux, *BSD, Mac OS X, Solaris, Windows
type |
libevent |
libev |
libuv |
dev/poll (Solaris) |
y |
y |
y |
event ports |
y |
y |
y |
kqueue (*BSD) |
y |
y |
y |
POSIX select |
y |
y |
y |
Windows select |
y |
y |
y |
Windows IOCP |
y |
N |
y |
poll |
y |
y |
y |
epoll |
y |
y |
y |
對於Unix/Linux平臺,沒有什麽大不同,優先選擇epoll,對於windows,libevent、libev都使用select檢測和分發事件(不I/O),libuv在windows下使用IOCP。libevent有一個socket handle, 在windows上使用IOCP進行讀寫。libev沒有類似的。但是libevent的IOCP支持也不是很好(性能不高)。所以如果是在windows平臺下,使用原生的IOCP進行I/O,或者使用libuv。
異步架構程序設計原則
1、回調函數不可以執行過長時間,因為一個loop中可能包含其他事件,尤其是會影響一些準確度要求比較高的timer。
2、盡量采用庫中所緩存的時間,有時候需要根據時間差來執行timeout之類的操作。當然能夠利用庫中的timer最好。
參考:http://zheolong.github.io/blog/libevent-libev-libuv/
https://cpp.libhunt.com/
網絡庫libevent、libev、libuv對比