iT邦幫忙

2021 iThome 鐵人賽

DAY 30
0
自我挑戰組

從C到JS的同步非同步探索系列 第 30

[Day 30] 模仿 Node 的非同步實驗兼完賽心得

實作

所謂讀了原始碼卻不實作與驗證, 那不過就是對原始碼的意淫而已, 所以在這個系列文的結尾總是還要寫點東西的。

但因為還有太多部分沒聊到, 所以我臨時把最後要完成的實作改成模仿我們前面讀到的 Node 原理做出來的小程式, 希望可以驗證一下我們前面學到的東西。

實作目的

利用最簡單的方法, 依照 Node 原理編寫一個程式具有可以處理非同步方法的環境, 並且具備幾個非同步方法供人調用。

概念與設計

打算在程式創建之初建立一個環境, 而這個環境支援數個非同步方法, 建完環境後就可以執行任意程式碼。

以下說明想要支援的非同步方法

  1. console_timer 特定延遲秒數後 console log
  2. console_file 讀取 local file 的文字, console log 出來
  3. console_encryption 加密替定文字後 console log 出來
  4. console_decryption 解密特定文字後 console log 出來

而環境的構成分成僅有一條 thread 的 event loop 和 有任意條 threads 的 thread pool

以下敘述 event loop 細節

  • 分成 4 個階段不斷循環, 藉此處理接踵而來的事件
  • 提供介面接收 main thread 和 thread pool 傳過來的事件, 以下說明介面
    1. main thread 運行 console_timer這類定時方法時, 調用介面把定時事件放入 event loop 中屬於 timer_stage 的最小樹。
    2. main thread 運行console_file 這類系統 IO 方法時調用 OS API 且註冊 IOCP 事件, 如此當 IO 結束 event loop 的 polling_stage 就可以收到該 IO 事件的結果了。
    3. console_encryption , console_decryption 這類密集 CPU 型方法被 thread pool 完成時透過 IOCP 方法送出結果, event loop 的 polling_stage 就可以收到該 IO 事件的結果了。
  • 以下敘述 4 個階段的細節
    1. timer_stage : 維護一個最小樹, 每當來到這個階段, 就檢查有沒有逾時的事件, 有就執行。
    2. pending_stage : 維護一個 pending_list , 每次來到此階段就執行整個 pending list 中的任務。最後把完成的任務放入 endgame list
    3. polling_stage : 利用 IOCP 方法接收 IO 結束的各種 AIO 事件, 再把事件放入 pending list
    4. endgame_stage : 維護一個 endgame_list , 每次來到此階段就釋放整個 endgame list 中任務的資源。

以下敘述 thread pool 細節

  • 透過 lock-free stack 來傳入任務, IOCP 來傳出結果, 兩個方法都是 multi-thread 的演算法, 所以支援無限大的 thread pool, 當然無限增大 TP 沒啥意義。
  • main thread 把 console_encryption , console_decryption 這類密集 CPU 型方法產生的事件加入 lock-free stack 只要 TP 中的 thread 閒置, 就會去 stack 取出一個任務來處理。
  • TP 中的 thread 完成事件中的任務後會利用 IOCP 的方法把事件傳給 event loop 中的 polling_stage。

程式碼

最後貼上程式碼, 其中有大量註解, 希望幫助大家看懂。

https://gist.github.com/leon123858/5b270a3c57f8744c4e4a334eb57f282e

聲明

這個系列文寫到這邊算是畫下一個句點了, 其中內容大多是我閱讀原始碼以及官方文件所得來, 這些東西真的是有點硬, 而且我這次又是挑選了 IOCP 路線來說(文件基本上都是 epoll 的版本), 導致我很多地方都只能半猜不猜得過去, 要是我有講錯說錯可以跟我反映, 我會做修訂。

後話與心得

不得不說, 30 天真的很短, 很多想寫的都還沒寫到就已經結束了。還有蠻多想聊的都還沒說到, 包含 node 中 await 的原理, threadpool 的 scheduling , .......... 等等。不過我想這篇不是完結, 我未來應該會把我在第一天中, 設定想寫的目標寫完, 那就暫時先跟大家說 bye bye 啦


上一篇
[Day 29] Node 非同步知識統整
系列文
從C到JS的同步非同步探索30

尚未有邦友留言

立即登入留言