電腦性能之殤(三)– 通用電子電腦的胎記:事件驅動
- 2019 年 12 月 30 日
- 筆記
摘要: 理解事件驅動。
Fundebug經授權轉載,版權歸原作者所有。
Event-Driven(事件驅動)這個詞這幾年隨著 Node.js® 的大熱也成了一個熱詞,似乎已經成了「高性能」的代名詞,殊不知事件驅動其實是通用電腦的胎記,是一種與生俱來的能力。本文我們就要一起了解一下事件驅動的價值和本質。
通用電子電腦中的事件驅動
首先我們定義當下最火的 x86 PC 機為典型的通用電子電腦:可以寫文章,可以打遊戲,可以上網聊天,可以讀U盤,可以列印,可以設計三維模型,可以編輯渲染影片,可以作路由器,還可以控制巨大的工業機器。那麼,這種電腦的事件驅動能力就很容易理解了:
- 假設 Chrome 正在播放 Youtube 影片,你按下了鍵盤上的空格鍵,影片暫停了。這個操作就是事件驅動:電腦獲得了你單擊空格的事件,於是把影片暫停了。
- 假設你正在跟人聊 QQ,別人發了一段話給你,電腦獲得了網路傳輸的事件,於是將資訊提取出來顯示到了螢幕上,這也是事件驅動。
事件驅動的實現方式
事件驅動本質是由 CPU 提供的,因為 CPU 作為 控制器 + 運算器,他需要隨時響應意外事件,例如上面例子中的鍵盤和網路。
CPU 對於意外事件的響應是依靠 Exception Control Flow(異常控制流)來實現的。
強大的異常控制流
異常控制流是 CPU 的核心功能,它是以下聽起來就很牛批的功能的基礎:
時間片
CPU 時間片的分配也是利用異常控制流來實現的,它讓多個進程在宏觀上在同一個 CPU 核心上同時運行,而我們都知道在微觀上在任一個時刻,每一個 CPU 核心都只能運行一條指令。
虛擬記憶體
這裡的虛擬記憶體不是 Windows 虛擬記憶體,是 Linux 虛擬記憶體,即邏輯記憶體。
邏輯記憶體是用一段記憶體和一段磁碟上的存儲空間放在一起組成一個邏輯記憶體空間,對外依然表現為「線性數組記憶體空間」。邏輯記憶體引出了現代電腦的一個重要的性能觀念:
記憶體局部性天然的讓相鄰指令需要讀寫的記憶體空間也相鄰,於是可以把一個進程的記憶體放到磁碟上,再把一小部分的「熱數據」放到記憶體中,讓其作為磁碟的快取,這樣可以在降低很少性能的情況下,大幅提升電腦能同時運行的進程的數量,大幅提升性能。
虛擬記憶體的本質其實是使用 快取 + 樂觀 的手段提升電腦的性能。
系統調用
系統調用是進程向作業系統索取資源的通道,這也是利用異常控制流實現的。
硬體中斷
鍵盤點擊、滑鼠移動、網路接收到數據、麥克風有聲音輸入、插入 U 盤這些操作全部需要 CPU 暫時停下手頭的工作,來做出響應。
進程、執行緒
進程的創建、管理和銷毀全部都是基於異常控制流實現的,其生命周期的鉤子函數也是作業系統依賴異常控制流實現的。執行緒在 Linux 上和進程幾乎沒有功能上的區別。
程式語言中的 try catch
C++ 編譯成的二進位程式,其異常控制語句是直接基於異常控制流的。Java 這種硬虛擬機語言,PHP 這種軟虛擬機語言,其異常控制流的一部分也是有最底層的異常控制流提供的,另一部分可以由邏輯判斷來實現。
基於異常控制流的事件驅動
其實現在人們在談論的事件驅動,是 Linux kernel 提供的 epoll,是 2002 年 10 月 18 號伴隨著 kernel 2.5.44 發布的,是 Linux 首次將作業系統中的 I/O 事件的異常控制流暴露給了進程,實現了本文開頭提到的 Event-Driven(事件驅動)。
Kqueue
FreeBSD 4.1 版本於 2000 年發布,起攜帶的 Kqueue 是 BSD 系統中事件驅動的 API 提供者。BSD 系統如今已經遍地開花,從 macOS 到 iOS,從 watchOS 到 PS4 遊戲機,都受到了 Kqueue 的蒙蔭。
epoll 是什麼
作業系統本身就是事件驅動的,所以 epoll 並不是什麼新發明,而只是把本來不給用戶空間用的 api 暴露在了用戶空間而已。
epoll 做了什麼
網路 IO 是一種純非同步的 IO 模型,所以 Nginx 和 Node.js® 都基於 epoll 實現了完全的事件驅動,獲得了相比於 select/poll 巨量的性能提升。而磁碟 IO 就沒有這麼幸運了,因為磁碟本身也是單體阻塞資源:即有進程在寫磁碟的時候,其他寫入請求只能等待,就是天王老子來了也不行,磁碟做不到呀。所以磁碟 IO 是基於 epoll 實現的非阻塞 IO,但是其底層依舊是非同步阻塞,即便這樣,性能也已經爆棚了。Node.js 的磁碟 IO 性能遠超其他解釋型語言,過去幾年在 web 後端霸佔了一些對磁碟 IO 要求高的領域。
相關日誌
- 性能之殤(一)– 天才馮·諾依曼與馮·諾依曼瓶頸
- 性能之殤(二)– 分支預測、流水線與多核 CPU
- 性能之殤(四)– Unix 進程模型的局限
- 性能之殤(五)– DPDK、SDN 與大頁記憶體
- 性能之殤(六)– 現代電腦最親密的夥伴:局部性與樂觀
- 性能之殤(七)– 分散式計算、超級電腦與神經網路共同的瓶頸
版權聲明
轉載時請註明作者 Fundebug以及本文地址: https://blog.fundebug.com/2019/01/02/about-computer-performance-part-3-event-driven/
您的用戶遇到BUG了嗎?
.copyright *{box-sizing:border-box}