库-libuv 和 libev的对比
From:?http://blog.chinaunix.net/uid-28458801-id-4463981.html
libuv?和?libev?,兩個名字相當相近的 I/O Library,最近有幸用兩個 Library 都寫了一些東西,下面就來說一說我本人對兩者共同與不同點的主觀表述。
高性能網絡編程這個話題已經被討論爛了。異步,異步,還是異步。不管是?epoll?也好,kqueue?也罷,總是免不了異步這個話題。
libuv是異步的,libev是同步的多路IO復用。
libev?是系統I/O復用的簡單封裝,基本上來說,它解決了?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 了,參見 commit665a316aa9d551ffdd00d1192d0c3d9c88d7e866?; 2. libuv 的線程池在BSS上,數量固定為4個,參見:https://github.com/joyent/libuv/blob/master/src/unix/threadpool.c#L28?; 3. libuv 的線程池共享一個work queue ,所以不會出現 block 的情況
libevent : 名氣最大,應用最廣泛,歷史悠久的跨平臺事件庫; libev : 較libevent而言,設計更簡練,性能更好,但對Windows支持不夠好; libuv : 開發node的過程中需要一個跨平臺的事件庫,他們首選了libev,但又要支持Windows,故重新封裝了一套,*nix下用libev實現,Windows下用IOCP實現;
libuv 源碼git下載
總結
以上是生活随笔為你收集整理的库-libuv 和 libev的对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: thinkphp3.22 多项目配置
- 下一篇: 顶岗实习周记java方向_java 实习