Muduo是C++語言實作的網絡庫,和Anet的設計目标基本一緻,各有千秋。希望通過閱讀Muduo能找到一些不一樣的靈感。
下面是本人最近分享muduo的ppt。性能對比圖和類圖是直接從muduo庫的manual手冊截過來的,其餘的是用libreoffice上畫出來。
概述:
1) muduo的抽象不錯的:概括上來說EventLoop 封裝了對事件的處理,這是client和server共有的邏輯,而且EventLoop和ThreadPool是解耦合的,為多線程IO模型奠定了基礎;TcpServer 封裝了Server端的邏輯和回調,比如acceptor。TcpClient封裝了client的邏輯和回調,比如connector。
2)muduo僅僅提供了3個最基礎的設施(事件處理,TimerQueue 和 functionQueue),并沒有提供像anet的timeout的機制,也沒有提供channelid。這些功能可以通過3個基礎設在muduo的上層實作。ppt最後一頁舉了個處理idle連結的例子。把所有的連結組織成8個boost::circle_buffer。并處理兩個事件:a)連結的建立,把conn的shared_ptr插入尾端;b)消息的到來,再一次把連結的shared_ptr再次插入尾端。同時,注冊一個定時器:每一秒往boost::circle_buffer尾部插入一個trival的結構,目的是每隔一秒淘汰首部的shared_ptr;當所有的格子裡的shared_ptr都淘汰之後,conn就被析構了。
3)性能展現在細節上。a)buffer的設計,muduo的buffer設計和anet如出一轍。b)read讀取資料,在棧上開64k的空間,使用readv,把目前conn的inputBuffer_和棧上開的空間組織一起,使用gatherIO。然後把棧上讀取到的資料copy到inputBuffer_。這樣既一次read調用可以盡量多的讀取資料,又不需要在inputBuffer預配置設定過多的空間。c)發送資料的時候,如果outputBuffer_上是空的,盡量直接發送出去,節省了outputBuffer_序列化的時間。這些實作都是基于muduo良好的基礎設施。d)多個IO線程,緩解關鍵線程的壓力。
4)多個IO處理線程。之前iSearch4的時候,1688的merger和searcher比例3:1,大部分是在收發資料,一個anet線程不能及時處理,因為IO線程并不是簡單的read,write。它還要負責packet的解析,上層應用的回調,這些都給關鍵的IO的線程帶來壓力。是以,面對萬兆網卡,或大吞吐量的應用,單個IO線程是吃力的。muduo的多IO線程的實作:1)中講到了EventLoop 隻是封裝了處理事件的邏輯,和執行體線程是解耦合的。開啟多IO線程時,開多個thread,每個thread綁定一個EventLoop。當一個連結建立之後,把這個連結路由給一個線程就可以了。
5)語言風格上。a)muduo大量使用了bind/function,這一對函數其實是在模仿‘閉包’的概念。把多線程并發做的事情,封裝成一個個的閉包,‘線性化’到EventLoop線程的functionQueue,同步化處理。使得在99%不需要鎖的地方,徹底無鎖了。犧牲的僅僅是一點點的串形化。同時,有了閉包,就不必到處繼承‘接口類’。是代碼也簡潔了一些。b)大量的使用了shared_ptr, weak_ptr管理資源,避免手工管理引用計數,像anet一樣。shared_ptr,weak_ptr的性能也很客觀,即使是頻繁的構造析構(當然,設計上能避免就避免構造析構。