ASIO 腾空出世 (那些年我们追过的网络库.PartII)
ASIO 騰空出世
在地球最大的島上,另一位少年開始拜讀 ACE 的大作。那時候,沒有 libuv 沒有 libev 更沒有 libevent . 有的只是 ACE. 然而這個南方小國的少年沒有跟風陷入 ACE 崇拜,他以敏銳的目光察覺到了 ACE 的弊病。 ACE 哪里做的不好?又哪里是值得借鑒的?
少年在給 c++ 委員會寫的一篇上書中說,Proactor 模型乃最優模型。而 Proactor 模型,乃 ACE 提出的 6 個模型之一。根據 IT 界贏者通吃律,一個優秀的網絡庫,只需要支持 Proactor 模型即可。 支持其他次優模型都是徒勞的。ACE 試圖全盤通吃,犯了大忌。
少年在一次開發者大會的演講上,再次透露,網絡庫不宜做成框架,而是要像系統的API那樣,作為一個樂高積木。ACE 做成了一個框架,同樣不妥。
你說了那么多 ACE 不好,有本事你弄個好的啊? 批評者向來都是這么理直氣壯。 正如 ACE 的作者實踐了 “紙上得來終覺淺 絕知此事要躬行” 一樣,這位勇敢的少年也拿出了 ASIO, “實踐出真知”,他如是說。
那還是 SARS 病毒肆虐的年代,幾乎沒有人注意到,今后顛覆C++的網絡世界的 ASIO 悄然出世了。而他的父親,還只是悉尼的學子。ASIO 并沒有顯赫的家庭背景,然而英雄不問出處,它注定將有不平凡的一生。
俗語有云,三歲看老。在 asio 才三歲的時候,它父親就將 asio 引薦給了 c++ 委員會的老人們。上一次他們這么做的時候,他們接納了 STL。 ASIO 最終被內定,然后放入 Boost 鍛煉, 經過 Boost 十余的鍛煉,ASIO 終于在 2017 年進入了 c++ 標準。
Proactor ? Why Proactor
在給 c++ 老人會的引薦信里,asio 爸爸仔細闡述了asio的設計抉擇回答了圍繞 asio 的設計提出的很多問題。 為什么 Proactor 會是最佳模型?
- 跨平臺 許多操作系統都有異步API,即便是沒有異步API的Linux, 通過 epoll 也能模擬 Proactor 模式。
- 支持回調函數組合 將一系列異步操作進行組合,封裝成對外的一個異步調用。這個只有Proactor能做到,Reactor 做不到。意味著如果asio使用Reactor模式,就對不起他“庫” 之名。
- 相比 Reactor 可以實現 Zero-copy
- 和線程解耦 長時間執行的過程總是有系統異步完成,應用程序無需為此開啟線程
Proactor 也并非全無缺點,缺點就是內存占用比 Reactor 大。Proactor 需要先分配內存而后處理IO, 而 Reactor 是先等待 IO 而后分配內存。相對的Proactor卻獲得了Zero-copy好處。因為內存已經分配好了,因此操作系統可以將接受到的網絡數據直接從網絡接口拷貝到應用程序內存,而無需經過內核中轉。 Proactor 模式需要一個 loop ,這個 loop asio 將其封裝為 io_service.他不僅是 asio的核心,更是一切基于asio設計的程序的核心。
宇宙級異步核心
io_service 脫胎于 IO 但不僅用于 IO. Christopher Kohlhoff 在給委員會的另一份編號 N3747 的信上上說它是?宇宙級異步模型?Universal Asynchronous Model。在宇宙級異步模型里,一個異步操作由三部分構成
在回調里發起新的異步操作,一輪套一輪。整個程序就圍繞著 io_service::run 運轉起來了。 io_service 不僅僅能用于異步 IO ,還可以用來投遞任意閉包。實現作為線程池的功能。這一通用型異步模型徹底擊敗微軟 PPL 提案,致使微軟轉而研究協程。然而微軟在協程上同樣面臨 asio 的絞殺。
閉包和協程
宇宙級 asio 使用閉包作為回調,而 C 庫只能使用函數+void*, ACE 雖然使用的 C++語言,卻不知道閉包為何物,使用的是 虛函數作為回調。需要大量的從 ACE 的對象繼承。以閉包為回調,asio更是支持了一種叫“無棧協程”的強悍武器。 asio的無棧協程,僅僅通過庫的形式,不論是在性能上,還是易用性上,還是簡潔性上,甚至是B格上,都超過了微軟易于修改語言而得的 await提案。
微軟,乃至 ACE ,并不是不知道閉包,而是在c++里實現閉包的宇宙級executor —— 也就是 io_service,需要對模板技術的精通。 asio “把困難留給自己,把方便帶給大家”,以地球人無法理解的方式硬是在 c++98 上實現了宇宙級異步核心。 當然,如果 c++11 早點出現,如果 c++17 早點出現,實現 asio 的宇宙模型會更加的簡單 —— 其實這也是 c++ 的理念,增加語言特性,只是為了讓語言用起來更簡單。
buffers
有了閉包的支持,內存管理也變得輕輕松松起來。 ASIO 本身并不管理內存,所有的IO操作,只提交對用戶管理的內存的引用,稱 Buffers。asio::buffers 引用了用戶提交的內存,保持整個 IO 期間,這塊內存的有效性是用戶的責任。然而這并不難! 因為回調是一個閉包。通過閉包持有內存,只要 asio 還未回調,閉包就在,閉包在,內存在。asio 在調用完回調后才刪除相應的閉包。因此資源管理的責任可以丟給閉包,而閉包可以通過智能指針精確的控制內存。 不是 GC , 勝于 GC 千百倍!益于c++的 RAII機制,再無內存泄漏之憂!
進入 ASIO 的世界
對 C++ 網絡庫的歷史也介紹到差不多了,接下來的章節里,帶你深入理解asio , 讓你同時獲得開發效率和執行效率。 一些在本章里,可能對許多人來說都是初次見到的技術,將在本書剩余章節里詳細介紹。
翻開下一頁,進入 ASIO 的世界,領略 C++ 的博大精深,享受網絡遨游的快感吧!
總結
以上是生活随笔為你收集整理的ASIO 腾空出世 (那些年我们追过的网络库.PartII)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 非对称加密, 助记词, PIN, WIF
- 下一篇: 一步步yum安装LNMP,脱坑笔记!!!