• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            陳碩的Blog

            學之者生,用之者死——ACE歷史與簡評

            學之者生,用之者死——ACE歷史與簡評

            陳碩 (giantchen_AT_gmail)

            Blog.csdn.net/Solstice

            2010 March 10

            ACE 是現代面向對象網絡編程的鼻祖,確立了許多重要模式,如 Reactor、Acceptor 等,重要到我們甚至覺得網絡編程就應該是那樣的。但為什么 ACE 叫好不叫座?大名鼎鼎卻使用者寥寥?本文談談我的個人觀點。

            ACE 是一套重量級的 C++ 網絡庫,早期版本由 Douglas Schmidt 獨自開發,后來有 40 余名學生與工作人員也貢獻了大量代碼。作者 Douglas Schmidt 憑借它發表了 30 余篇學術論文。ACE 的一大特點是融合了 Douglas Schmidt 提出的很多面向對象網絡編程的設計模式,并且具有不可思議的跨平臺能力

            1 ACE 歷史

            先說說 ACE 之父 Douglas Schmidt 的個人經歷

            我相信 ACE 是 Douglas 在讀博期間的主要工作,ACE 這個名字最早出現在 1993 年 12 月的一篇會議論文上,Douglas 的這篇文章獲得了“最佳學生論文”獎。在此之前,Douglas 已經用 ASX 等其他名字發表了內容相近的文章。

            我能下載到的最早的 ACE 版本是 4.0.32,有大約 86,000 行 C++ 代碼,代碼的時間戳是 1998 年 10 月 22 日。早期 ACE 由 Douglas Schmidt 個人獨立開發,從 ChangeLog 得知,1993 年 11 月 ACE 的版本號是 2.12。到了 1995 年 9 月,才有第一次出現其他開發者。在 1993~1996 年間的 684 次改動中,Douglas 一個人貢獻了 529 次,另外幾個主要開發者以及他們的修改次數分別是 Prashant Jain (58)、Tim Harrison (42)、David Levine (28)、Irfan Pyarali (20)、Jesper S. M|ller (5)。

            從整個 ChangeLog 看,從 1993 年到 2010 年 3 月有 19,000 余次改動。有超過 200 人修改過代碼,其中 23 個人的 check-in 次數大于 100,排名前 12 的代碼修改者為:

               3635  Johnny Willemsen (活躍年份:2001~今)

               2586  Douglas C. Schmidt(原作者,活躍年份:1993~今)

               1861  Steve Huston (活躍年份:1997~今)

               1197  David L. Levine  (活躍年份:1996~2000)

                962  Nanbor Wang  (活躍年份:1998~2003)

                907  Ossama Othman (活躍年份:1999~2005)

                865  Chad Elliott (活躍年份:2000~今)

                823  Bala Natarajan (活躍年份:1999~2004)

                708  Carlos O'Ryan (活躍年份:1997~2001)

                544  J.T. Conklin (活躍年份:2004~2008)

                479  Irfan Pyarali (活躍年份:1996~2003)

                368  Darrell Brunsch (活躍年份:1997~2001)

            看到這些“活躍年份”,你的第一反應是什么?我想到的是,這些人會不會多半是 Douglas 指導的研究生?我猜他們在讀研期間參與改進 ACE,把工作內容寫成論文發表,然后畢業走人。或許這能解釋 ACE 代碼風格的多樣性。

            在瀏覽代碼歷史的過程中,我還發現一個很有意思的現象,在 2008 年 3 月 4 日,某人不小心把整個 ACE 的源代碼樹刪除了:

            https://svn.dre.vanderbilt.edu/viewvc/Middleware?view=revision&revision=80824

            隨后又很快恢復:

            https://svn.dre.vanderbilt.edu/viewvc/Middleware?view=revision&revision=80826

            干這件事情的老兄在 2005~2009 這幾年里一共 check in 了 120 余次。你對這件事情怎么看?你們的開發團隊里有這樣的人嗎?

            2 事實與思考

            1. 除了 Douglas Schmidt 和 Stephen Huston 寫的三本書籍之外,沒有其他專著講 ACE。

            究竟是 ACE 太好用了,以至于無需其他書來講解,還是太難用了,講也講不明白?抑或根本就沒人在乎?

            C++ 網絡編程 第1卷》《C++ 網絡編程 第2卷》《ACE 程序員指南》這三本書先后于 2001、2002、2003 年出版,之后再無更新。在同一時期,同樣在網絡編程領域,盡管 W. Richard Stevens 在 1999 年去世,他的 UNP 和 APUE 仍然由別人續寫了新版。講 C 語言 Sockets API 的書尚且不斷更新,上層封裝的 C++ 居然無動于衷?真的是封裝到位了,屏蔽了這些變化?

            UNP 的可操作性很強,讀前面幾章,就能上手編寫簡單的網絡程序,看完大半本書,網絡編程基本就算入門了,能編寫一般應用的網絡程序。相反,讀完 ACE 那幾本書,對于簡單的網絡編程任務還是感覺無從下手,這是因為書寫得不好,還是 ACE 本身不好用?

            2. ACE 很難用,非常容易用錯

            我不止聽到一個人對我說,他們在項目里嘗試過 ACE,不是中途放棄,因為出了問題無法解決;就是勉強交差,并且從下一個項目起堅決不用。我聽到的另一個說法是,ACE 教程的例子必須原封不動地抄下來,改一點點就會出漏子。不巧的是,ACE 的例子舉來舉去就是個 Logging 服務器,讓人想照貓畫虎也無從下手。在最近的《代碼之美》一書中,Douglas Schmidt 再次拿它為例,說明他真的很喜歡這個例子。

            用 ACE 編程如履薄冰,生怕在陰溝里翻船,不知道它背后玩了什么把戲。相反,用 10 來個 Sockets 系統調用就能搞定網絡編程,我感覺比使用 ACE 難度要小。為什么“高級”工具反而沒有低級工具順手呢?

            不好用的直接后果是少有人用,放眼望去,目前涉及網絡的 C++ 開源項目里邊,鮮有用 ACE 作為通信平臺的(我知道的只有 Mangos)。相反,libevent 這個輕量級的 IO multiplexing 庫有 memcached 這樣的著名用戶。

            3. ACE 代碼質量不高,更像是一個研究項目,而不是工業界的產品

            讀 ACE 現在的代碼,一股學生氣撲面而來,感覺像在讀實習生寫的代碼。拋開編碼風格不談,這里舉三個“硬傷”:

            • sleep < 2ms

            在某些早期的 Linux 內核上,如果 select/poll 的等待時間小于 2ms,內核會采用 busy-waiting。這是極大的 CPU 資源浪費,而 ACE 似乎沒有考慮避免這一點。

            • Linux TCP self-connection

            Linux 的 TCP 實現有一個特殊“行為”,在某些特殊情況下會發起自連接。而 Linux 網絡協議棧的維護者認為這是一個 feature,不是 bug,拒絕修復。通常網絡應用程序不希望出現這種情況,我見過的好的網絡庫會有意識地檢查并斷開這種連接,然而 ACE 漠然視之。

            • timeval on 64-bit

            ACE_Time_Value 類直接以 struct timeval 為成員變量,保存從 Epoch 開始的微秒數。這在 32-bit 下沒問題,對象大小是 8 字節。到了 LP64 模式的 64-bit 平臺,比如 Linux,對象大小變為 16 字節,這么做就不夠好了。我們可以直接用 int64_t 來保存這個以微秒為單位的時間,64-bit 整數能存下上下 30 萬年,足夠用了。減小對象大小并不是為了節約幾個字節的內存,而是方便函數參數傳遞。在 x86-64 上,這種 8 字節的結構體可以用 64-bit 寄存器直接傳參,也就是說 pass by value 會比 pass by reference 更快。對于一般的應用程序而言,要不要這么做值得商榷。對于底層的 C++ 網絡庫,不加區分地使用 pass by reference 會讓人懷疑作者知其然不知其所以然。

            對于以上幾點情況,我懷疑 ACE 根本沒用在 Linux 大規模生產環境下使用過,我只能期望它在別的平臺表現好一些了。ACE 的作者們似乎更注重驗證新想法,然后發論文,而不是把它放到工業環境中反復錘煉,打造為靠得住的產品。(類似 Minix 與 Linux 的關系。)

            4. 移植性很好,支持我知道的和不知道的很多平臺

            ACE 的意義在于讓我們明白了C++代碼可以做到可移植,并展示了這么做會付出多么巨大的代價。不細說了,讀過 ACE 代碼的人都明白。

            從代碼質量上看,ACE 做到了能在這些平臺上運行,但似乎沒有在哪個平臺占據主導地位。有沒有哪個平臺的網絡編程首選 ACE?

            出現這一狀況的原因是,跨平臺和高性能是矛盾的。跨平臺意味著要抽象出多個平臺的共性,以最 general 的方式編寫上層代碼。而高性能則要求充分發揮平臺的特性,劍走偏鋒,用盡平臺能提供的一切加速手段,哪怕與其他平臺不兼容。網絡編程對此尤為敏感。

            我不知道 ACE 的性能如何,因為在各項性能評測榜上基本看不到它的名字(c10k 里就沒有 ACE 的身影)。另外,Buffer class 的好壞直接反應了網絡庫對性能的追求,ACE 提供了比 std::deque<uint8_t> 更好的輸入輸出 Buffer 嗎?(我不是說 deque 有多好,它基本是 fail-safe 的選擇而已。)

            5. ACE 過于復雜,甚至比它試圖封裝的對象更復雜。

            (這里的代碼行數均為 wc 命令的粗略估計。)

            ACE 5.7 自身(不含 TAO 和 CIAO)有 30 萬行 C++ 代碼(Douglas 自己給出的數據是 25 萬行,可能指的是略早的版本),這是一個什么概念呢?我們來看 TCP/IP 協議棧本身的實現有多少行:(均不含 IPv6)

            • TCPv2 列出的 BSD4.4-Lite 完整 TCP/IP 協議棧代碼有 15,000 行,其中 4,500 行 TCP 協議,800 行 UDP 協議,2,500 行 IP 協議  
            • Linux 1.2.13 完整的 TCP/IP 協議棧有 2 萬多行 (net/inet)  
            • Linux 2.6.32.9 的 TCP/IP 協議棧有 6 萬多行 (net/ipv4)  
            • FreeBSD 8.0 的 TCP/IP 協議棧有 5 萬多行 (sys/netinet, 不含 sctp)

            換句話說,ACE 用 30 萬行 C++ 代碼“封裝”了不到 10 萬行 C 代碼(且不論 C++ 代碼的信息密度比 C 大),這是不是頭重腳輕呢?我理解的“封裝”是把復雜的東西變簡單,但 ACE 好像走向了另一個方向,把不那么復雜的東西變復雜了。

            這個對比數字可能不太準確,因為 ACE 還封裝了很多其他東西,請看。http://www.dre.vanderbilt.edu/Doxygen/5.7.7/html/ace/inherits.htmlhttp://www.dre.vanderbilt.edu/Doxygen/5.7.7/html/ace/hierarchy.html

            以下兩張類的繼承關系圖片請在新窗口打開:

            http://www.dre.vanderbilt.edu/Doxygen/5.7.7/html/ace/a06178.png

            http://www.dre.vanderbilt.edu/Doxygen/5.7.7/html/ace/a06347.png

            Douglas 說 ACE 包含了 40 人年的工作量,對此我毫不懷疑。但是,網絡編程真的需要這么復雜嗎?TCP/IP 協議棧的實現也沒這么多工作量嘛。或許只有 CORBA 這樣的應用才會用到這么復雜的東西?那么為什么 ICE 在重新實現 CORBA 的時候沒有基于 ACE 呢?是不是因為 ACE 架子拉得大,底子并不牢?

            3 ACE 的意義

            ACE 對于面向對象、設計模式和網絡編程具有重大歷史和現實意義。

            ACE 誕生之時,正是 90 年代初期面向對象技術的高速發展期,ACE 一定程度上是作為面向對象技術的成功案例來宣傳的。

            在 1994 年前后,Unix 分為兩個陣營,AT&T 的 SVR4 與 BSD 的 BSD4.x,這兩家的 IO multiplexing 不完全兼容。比如 SVR4 提供 poll 調用,而 BSD 提供 select 調用。ACE 當時的宣傳點之一是用面向對象技術屏蔽了兩個平臺的差異,提供了統一的 Reactor 接口。

            【接下來,poll 在 1996 年 9 月 7 號加入 NetBSD,并隨 NetBSD 1.3 于 1998 年 1 月 4 號發布。隨后 FreeBSD 3.0 也支持 poll,1998 年 10 月發布。Linux 很早就支持 select,從 2.1.23 內核起支持 poll,發布日期為 1997 年 1 月 26 號。也就是說,到了 1998 年,平臺差異被暫時抹平了。隨后 epoll、/dev/poll、kqueue 以性能為名,再次擴大了平臺差異。當然,Windows 至今不支持 poll。】

            ACE 的設計似乎過于強調面向對象的靈活性,一些不該使用虛函數的地方也提供了定制點,比如 ACE_Timer_Queue 就應是個具體類,而不是允許用戶 override schedule/cancel/expire 之類的操作。面向對象中,“繼承”的目的是為了被復用,而不是去復用基類的代碼。

            查其文獻,Reactor 在 1993 年登上《C++ Report》雜志的時候,文章標題還比較樸素,掛著“面向對象”的旗號:

            轉眼到了 1994 年,也就是《設計模式》成書的那一年,Douglas 開始寫文章言必稱 pattern:

            似乎 "pattern" 這個字樣成了發文章的通行證,這股風氣直到 2000 左右才剎住。之后這些論文集結出版,以《Pattern-Oriented Software Architecture》為名出了好幾本書,ACE 的內容主要集中在第二卷。(請留意,原來的提法是 Object-Oriented,現在變成了 Pattern-Oriented,似乎軟件開發就應該像糖果廠生產綠豆糕,用模子一個個印出來完事。)

            ACE 就像一個 pattern 大觀園,保守估計有 10 來種 patterns 藏身其中,形成了一套模式語言(《Applying a Pattern Language to Develop Application-level Gateways》),這還不包括 GoF 定義的一般意義下的 OO pattern。

            通過 ACE 來學習網絡編程,那是本末倒置,因為它教不了你任何 UNP 以外的知識。(Windows 網絡編程?)

            然而,如果要用面向對象的方式來搞網絡編程,那么 ACE 的思想(而不是代碼)是值得效仿的,畢竟它飽含了 Douglas Schmidt 等學者的心血與智慧。學得好的例子有 Apache Mina、JBoss Netty、Python Twisted、Perl POE 等等。

            這就是我說“學之者生,用之者死”的含義。

            4 ACE 文獻導讀

            Douglas Schmidt 寫了很多 ACE 的文章,其中不乏內容相近的作品。讀他的文章,首選發表在技術雜志上的文章(比如 C++ Report),而不是發表在學術期刊或會議上的論文。前者的寫作目的是教會讀者技術,后者則往往是展示作者的新思路新想法,技術文章比學術論文要好讀得多。

            由于當時面向對象技術尚在發展,Douglas 文章里的圖形很有特色,不是現在規范的 UML 圖(那會兒 UML 還沒定型呢),而是像變形蟲一樣的類圖(經 pinxue 指出,這種圖是 Grady Booch 發明的),放在一堆文獻里也很容易認出來。

            如果要用 ACE 的代碼來驗證文章的思路,我建議閱讀和文章同時期的 4.0 版本代碼,代碼風格比較統一,代碼量也不大,便于理解。

            下面介紹幾篇有代表性的論文。

            以上兩篇文章實際上內容基本相同,都是對 ACE 的概要介紹,看第二篇即可,第一次沒看懂也沒關系。

            剩下要看的是一篇 Socket OO 封裝、四篇 Reactor、三篇 Acceptor-Connector、一篇 Proactor。這些文章前面大多都給了鏈接,其余的這里補充一下:

            不想看這 10 篇論文的話,讀中譯本《C++ 網絡編程 第1卷》《C++ 網絡編程 第2卷》《ACE 程序員指南》也行,翻譯質量都不錯。

            5 設想中的 C++ 網絡庫

            與文章主旨無關,略。

            我覺得網絡庫要解決現實的問題,滿足現實的需要,而不是把 features/patterns 堆在那里等別人來用。應該先有應用,再提煉出庫。而不是先造庫,然后尋求應用。

            posted on 2010-03-11 20:34 陳碩 閱讀(6647) 評論(4)  編輯 收藏 引用

            評論

            # re: 學之者生,用之者死——ACE歷史與簡評 2010-03-11 21:29 空明流轉

            寫的相當好。  回復  更多評論   

            # re: 學之者生,用之者死——ACE歷史與簡評 2010-03-12 16:37 hdqqq

            用協議棧代碼和ace代碼對比欠妥,基礎層要提供的接口和要實現的功能相對固定,而在應用層上,要復雜很多。  回復  更多評論   

            # re: 學之者生,用之者死——ACE歷史與簡評 2010-03-12 16:44 chentan

            "應該先有應用,再提煉出庫。而不是先造庫,然后尋求應用。"


            這句話非常好,也是我一直的信條


              回復  更多評論   

            # re: 學之者生,用之者死——ACE歷史與簡評 2010-03-12 19:36 陳昱(CY)

            "應該先有應用,再提煉出庫。而不是先造庫,然后尋求應用。"

            應該先有游戲,再提煉出引擎,而不是先造引擎,然后尋求游戲

            看來我找到失敗的原因了  回復  更多評論   

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            常用鏈接

            隨筆分類

            隨筆檔案

            相冊

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲av伊人久久综合密臀性色| 一本大道加勒比久久综合| 九九精品久久久久久噜噜| 久久午夜免费视频| 久久国产乱子精品免费女| 久久久亚洲精品蜜桃臀| 漂亮人妻被黑人久久精品| 国产精品一区二区久久精品无码 | 久久精品免费全国观看国产| 97久久国产露脸精品国产| 91久久精品国产成人久久| 久久精品亚洲AV久久久无码| 97超级碰碰碰碰久久久久| 国产毛片欧美毛片久久久| 国产精品久久久久久久久久免费| 日韩精品久久无码中文字幕| 久久久久99精品成人片| 久久久久综合网久久| 漂亮人妻被黑人久久精品| 国产精品久久久久久久久软件| 亚洲欧美日韩精品久久| 久久精品黄AA片一区二区三区| 日本WV一本一道久久香蕉| 国产精品免费久久久久影院| 久久99精品国产自在现线小黄鸭 | 久久久久亚洲AV综合波多野结衣 | 一级做a爰片久久毛片看看| 一级做a爰片久久毛片16| 国产精品久久久久影院色| 麻豆成人久久精品二区三区免费| 久久国内免费视频| 国产69精品久久久久APP下载 | 99久久综合国产精品二区| 狠狠色婷婷久久一区二区三区| 色欲综合久久中文字幕网| 日韩精品无码久久久久久| 亚洲AV无码久久| 99久久精品国产麻豆| 久久久国产精品福利免费| 国产福利电影一区二区三区久久久久成人精品综合 | 国产精品久久永久免费|