iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
自我挑戰組

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

[Day 28] Node thread pool 3

前言

今天的內容是整理整個 threadpool (TP) 的調用過程

回顧

在 pending 階段當遇到 async 類型的任務會執行以下這段

void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
    uv_req_t* req) {
  assert(handle->type == UV_ASYNC);
  assert(req->type == UV_WAKEUP);

  handle->async_sent = 0;

  if (handle->flags & UV_HANDLE_CLOSING) {
    uv_want_endgame(loop, (uv_handle_t*)handle);
  } else if (handle->async_cb != NULL) {
    handle->async_cb(handle);
  }
}

我們等下來看看 async_cb 是調用了甚麼方法

正文

回去翻原始碼, 選了其中一種 case , 以下假設 async_cb 調用的是以下方法

void uv__work_done(uv_async_t* handle) {
  struct uv__work* w;
  uv_loop_t* loop;
  QUEUE* q;
  QUEUE wq;
  int err;

  loop = container_of(handle, uv_loop_t, wq_async);
  uv_mutex_lock(&loop->wq_mutex);
  QUEUE_MOVE(&loop->wq, &wq);
  uv_mutex_unlock(&loop->wq_mutex);

  while (!QUEUE_EMPTY(&wq)) {
    q = QUEUE_HEAD(&wq);
    QUEUE_REMOVE(q);

    w = container_of(q, struct uv__work, wq);
    err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
    w->done(w, err);
  }
}

其內容是讀取 work queue 中由 TP 完成 IO 的任務, 繼續接下去把當初在上層設置的 callback 跑完。

結論

node 的 threadpool 機制可以稱得上是十分複雜, 在探索的過程中, 有部分我也看得不是很懂, 也有因為篇幅問題做一些省略, 接著我試著用我個人的理解大概講述一下 node 的 threadpool。

首先要理解 threadpool 執行的不是我們在 JS 層直接撰寫的程式碼, 其主要目的是處理 IO 的等待時間還有做基本的資料搬運。

舉個簡單的例子, 當 node 要讀取一張圖片且進行修圖需要經過幾個動作。

  1. 調用 OS api 讀取圖片
  2. 等待 OS 把圖片的資料複製到 user space
  3. 對該圖片的資料進行運算 ( 修圖 )
  4. 調用 OS api 把圖片的資料回存

TP 能處理的就是步驟 1,2,4 。第3步會在 main thread 的 pending stage 執行。

所以我們可以認知 node 的 TP 是專門平行化特定任務 ( AIO ) 的。

接著我們按照步驟來講講 threadpool 的運行吧

  1. JS 層註冊非同步 IO 事件 ( 後稱 AIO event ) 與其對應 callback
  2. C++ 層把任務包裝好後放入 TP 執行 AIO
  3. TP 每執行完一個 AIO 後都會觸發已被註冊的 IOCP 事件
  4. IOCP 把該事件放入 IOCP queue
  5. run_uv 的 polling stage 抓取 IOCP queue 的事件, 放入 pending queue
  6. run_uv 的 pending stage 抓取 pending queue 的事件, 執行 uv__work_done
  7. 掃描 TP 已完成任務列表 (wq) , 逐一執行他們在更上層定義的 callback
  8. run_uv endgame stage 抓取已完成 AIO 事件, 進行關閉。

明天進度

今天聊完了 Node , 我明天會為這段時間 Node 的內容作些整理。

明天見 !


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

尚未有邦友留言

立即登入留言