libuv和libev 異步I/O庫的比較

libuv 和 libev ,兩個名字至關相近的 I/O Library,最近有幸用兩個 Library 都寫了一些東西,下面就來講一說我本人對二者共同與不一樣點的主觀表述。html

高性能網絡編程這個話題已經被討論爛了。異步,異步,仍是異步。不論是 epoll 也好,kqueue 也罷,老是免不了異步這個話題。git

1.使用:

libev 是系統異步模型的簡單封裝,基本上來講,它解決了 epoll ,kqueuq 與 select 之間 API 不一樣的問題。保證使用 livev 的 API 編寫出的程序能夠在大多數 *nix 平臺上運行。可是 libev 的缺點也是顯而易見,因爲基本只是封裝了 Event Library,用起來有諸多不便。好比 accept(3) 鏈接之後須要手動 setnonblocking 。從 socket 讀寫時須要檢測 EAGAIN 、EWOULDBLOCK 和 EINTER 。這也是大多數人認爲異步程序難寫的根本緣由。程序員

libuv 則顯得更爲高層。libuv 是 joyent 給 Node 作的一套 I/O Library 。而這也致使了 libuv 最大的特色就是到處回調。基本上只要有可能阻塞的地方,libuv 都使用回調處理。這樣作實際上大大減輕了程序員的工做量。由於當回調被 call 的時候,libuv 保證你有事可作,這樣 EAGAIN 和 EWOULDBLOCK 之類的 handle 就不是程序員的工做了,libuv 會默默的幫你搞定。github

2.讀寫事件

libev 在 socket 發生讀寫事件時,只告訴你,「XX socket 能夠讀/寫了,本身看着辦吧」。每每咱們須要本身申請內存並調用 read(3) 或者 write(3) 來響應 I/O 事件。編程

libuv 則稍微複雜一些,咱們分讀/寫兩個部分來描述。c#

當接口可讀時,libuv 會調用你的 allocate callback 來申請內存並將讀到的內容寫入。當讀取完畢後,libuv 會 call 你爲這個 socket 設置的回調函數,在參數中帶着這個 buffer 的信息。你只須要負責處理這個 buffer 而且free 掉就OK了。由於是從 buffer 中讀取數據,在你的 callback 被調用時數據已經 ready 了,因此程序員也就不用考慮阻塞的問題了。網絡

而對寫的處理則更顯巧妙。libuv 沒有 write callback ,若是你想寫東西,直接 generate 一個 write request 連着要寫的 buffer 一塊兒丟給 libuv ,libuv 會把你的 write request 加進相應 socket 的 write queue ,在 I/O 可寫時按順序寫入。多線程

C 沒有閉包,因此肯定讀寫上下文是 libuv 的使用者須要面對的問題。不然程序面對洶涌而來的 buffer 也不能分得清哪一個是哪一個的數據。在這一點的處理上,libuv 跟 libev 同樣,都是使用了一個 void *data 來解決問題。你能夠用 data 這個 member 存儲任何東西,這樣當 buffer 來的時候,只須要簡單的把 data cast 到你須要的類型就 OK 了。閉包

3.DNS解析

libev 沒有異步 DNS 解析,這一點一直廣爲垢病。異步

libuv 有異步的 DNS 解析,解析結果也是經過回調的方式通知程序。

4.多線程

libev 徹底是單線程的。

libuv 須要多線程庫支持,由於其在內部維護了一個線程池來 handle 諸如 getaddrinfo(3) 這樣的沒法異步的調用。

5.IOCP

libev 不支持 IOCP ,若是須要在 Win 下運行的程序會很麻煩。

libuv 支持 IOCP ,有相應腳本編譯 Win 下的庫。

6.社區

libev 貌似是做者一我的在開發,版本管理使用的仍是 CVS ,社區參與度明顯不高。

libuv 社區十分活躍,幾乎天天都有人提出 Issue 並貢獻代碼。

 

原文:http://blog.csdn.net/w616589292/article/details/46475555

http://www.cnblogs.com/ningskyer/articles/5879503.html

---------------------------------------------------------------------------------------------------------

05 January 2013

libuv 和 libev ,兩個名字至關相近的 I/O Library,最近有幸用兩個 Library 都寫了一些東西,下面就來講一說我本人對二者共同與不一樣點的主觀表述。

高性能網絡編程這個話題已經被討論爛了。異步,異步,仍是異步。不論是 epoll 也好,kqueue 也罷,老是免不了異步這個話題。

libev 是系統異步模型的簡單封裝,基本上來講,它解決了 epoll ,kqueuq 與 select 之間 API 不一樣的問題。保證使用 livev 的 API 編寫出的程序能夠在大多數 *nix 平臺上運行。可是 libev 的缺點也是顯而易見,因爲基本只是封裝了 Event Library,用起來有諸多不便。好比 accept(3) 鏈接之後須要手動 setnonblocking 。從 socket 讀寫時須要檢測 EAGAIN 、EWOULDBLOCK 和 EINTER 。這也是大多數人認爲異步程序難寫的根本緣由。

libuv 則顯得更爲高層。libuv 是 joyent 給 Node 作的一套 I/O Library 。而這也致使了 libuv 最大的特色就是到處回調。基本上只要有可能阻塞的地方,libuv 都使用回調處理。這樣作實際上大大減輕了程序員的工做量。由於當回調被 call 的時候,libuv 保證你有事可作,這樣 EAGAIN 和 EWOULDBLOCK 之類的 handle 就不是程序員的工做了,libuv 會默默的幫你搞定。

libev 在 socket 發生讀寫事件時,只告訴你,「XX socket 能夠讀/寫了,本身看着辦吧」。每每咱們須要本身申請內存並調用 read(3) 或者write(3) 來響應 I/O 事件。

libuv 則稍微複雜一些,咱們分讀/寫兩個部分來描述。

當接口可讀時,libuv 會調用你的 allocate callback 來申請內存並將讀到的內容寫入。當讀取完畢後,libuv 會 call 你爲這個 socket 設置的回調函數,在參數中帶着這個 buffer 的信息。你只須要負責處理這個 buffer 而且 free 掉就OK了。由於是從 buffer 中讀取數據,在你的 callback 被調用時數據已經 ready 了,因此程序員也就不用考慮阻塞的問題了。

而對寫的處理則更顯巧妙。libuv 沒有 write callback ,若是你想寫東西,直接 generate 一個 write request 連着要寫的 buffer 一塊兒丟給libuv ,libuv 會把你的 write request 加進相應 socket 的 write queue ,在 I/O 可寫時按順序寫入。

C 沒有閉包,因此肯定讀寫上下文是 libuv 的使用者須要面對的問題。不然程序面對洶涌而來的 buffer 也不能分得清哪一個是哪一個的數據。在這一點的處理上,libuv 跟 libev 同樣,都是使用了一個 void *data 來解決問題。你能夠用 data 這個 member 存儲任何東西,這樣當 buffer 來的時候,只須要簡單的把 data cast 到你須要的類型就 OK 了。

libev 沒有異步 DNS 解析,這一點一直廣爲垢病。

libuv 有異步的 DNS 解析,解析結果也是經過回調的方式通知程序。

libev 徹底是單線程的。

libuv 須要多線程庫支持,由於其在內部維護了一個線程池來 handle 諸如 getaddrinfo(3) 這樣的沒法異步的調用。

libev 貌似是做者一我的在開發,版本管理使用的仍是 CVS ,社區參與度明顯不高。

libuv 社區十分活躍,幾乎天天都有人提出 Issue 並貢獻代碼。

libev 不支持 IOCP ,若是須要在 Win 下運行的程序會很麻煩。

libuv 支持 IOCP ,有相應腳本編譯 Win 下的庫。

-----------------------------------------------------------------------------------

Q: 博主有沒作過二者的benchmark,他們以前的性能對好比何?

A: 當時用 libev 和 libuv 寫過一個簡單的 HTTP Hello World Server 。具體結果記不清楚了可是能夠說性能差距在 5% 之內。

Q:  libuv 在 unix 上應該是用 libev 做爲 non-blocking IO 的實現的吧?libuv 中線程池裏線程的數量會增長麼,是否會有上限?若是上限到了是否是就會出現 block 的狀況?

A: 1. libuv 在大概5個月前已經徹底不使用 libev 了,參見 commit 665a316aa9d551ffdd00d1192d0c3d9c88d7e866 ; 2. libuv 的線程池在BSS上,數量固定爲4個,參見:https://github.com/joyent/libuv/blob/master/src/unix/threadpool.c#L28 ; 3. libuv 的線程池共享一個work queue ,因此不會出現 block 的狀況

 

https://my.oschina.net/jacobin/blog/146735

相關文章
相關標籤/搜索