[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 16] 每个模型我全都要 - 堆叠法 (Stacking)

>>:  30天学会C语言: Day 12-自订函式

Day 25:「好慢喔,下载多少了?」- 进度条

终於到了我们的元件篇啦!!! 今天是第一个元件,所以稍微简单一点。 我们要来做下载的进度条~ 前置...

【Day29】this - DOM

今天要来讲解 DOM 与 this 的关系, 对於 DOM 的操作有两种方式, 第一种是直接将方法写...

Day 26 「一个巨星的诞生」Entity、Repository 与单元测试

通常一个活动,最後登场的都是主角吧?理应如此,笔者记得有一年的金马奖颁奖典礼,主办单位不知道哪根筋打...

Day8 Swagger UI & Open Match APIs

Swagger UI 是一个将 API 文件与 API 请求产生结合的介面套件,官方已於建立核心的 ...

Android学习笔记10

今天来用kotlin实作一个BaseActivity,方便以後跳页传值使用 fun start(ne...