AdvancedConcepts
Eng
The internals of NodeJS
Find where its implemented in the Node source code
takes in parameters
scroll back to the top
translate it to the C++ equivalents
To clearify A very common misconception about xx
from time to time...时不时的
we're going to eventually..
give us a better sense in .. // 有更好的意识
we can get access to,,
There are some corner cases to be aware of..
concrete reslut
thats what you might think..
notes
- Javascript -> Node JS(50% js 50%c++) -> V8(70%JS+30%C++) + libuv(100%C++)
In another saying, V8 is used to interpret and execute JS code, while libuv is used for accessing the file sysytem and some aspects of concurrency.
- Module implementations - e.g. 'crypto' library
Node source code:
-
lib folder: JS definition for modules [通过 process.binding('crypto')这道 bridge]
-
src folder: (c++ implementations) node_cryto.cc --- kind of bind its function to the environment
using v8::Context;
using v8::Local;
...
// importing the c++ definitions of javascript definitions
Uv_work_t*
libuv is used for a lot of concurrency
threads
-
进程 process: A process is an instance of a computer program that is being executed within a single process.
-
线程 thread: OS Scheduler has to decide which thread should be processed
-
A: How to improve the rate at which these threads being processed?
Q: 1. Add in additional CPU cores to our machine. 2. Allow our OS scheduler to detect big pauses in processing time due to expensive input and output operations.
The thing to keep in mind is that any time our computer tries to read data off of some type of medium, like a hard drive, we refer to that as input or output operations, and it always takes some non-zero amount of time.
-
一个 Node Program 一个 Thread --> Every time the event loop runs in a node application is called a tick
-
A: Under what conditions, a node program may be held from exiting?
Q: 1. Any pending setTimeout, setInterval, setImmediate. 2. Any pending OS tasks (Like server listening to port) 3. Ant pending long running operations (Like fs module)
- A: Is Node signle thread?
Q: Node Event Loop: Single ~
some modules' C++ side + libuv: Not single ~ They use thread pool (by default 4 threads) to do the work
Normally 1s a time. Notice that the fourthest ones take double time while fifth one takes 1 additional second.
- A: What function in node std library use the threadpool?
Q: All 'fs' function. Some crypto stuff. Etc.
- 对于一些更底层的模块,比如 https 就是 libuv 直接代理 os 的调用, os 有多核的话就当然也是多线程的
整体 node 运行图例:
事件循环需要经历 6 个阶段,统称为一个 tick.
- timers:这个阶段执行定时器 setTimeout() 和 setInterval() 的回调函数。
- pending callbacks:几乎所有其他回调(除了 close 回调、定时器 timers 阶段的回调和 setImmediate())
- idle, prepare: 仅在内部应用。
- poll:检索新的 I/O 事件;适当时 Node 将在此处阻塞。
- check:setImmediate() 回调函数将在这里执行。
- close callbacks: 一些准备关闭的回调函数,如:socket.on('close', ...)。
这一节关于 The internals of Node 作者讲了一些很有趣的东西!
比如 file 模块 和 crypto 模块会用 threadpool,当调用这些模块时,它们会根据 threadpool_size 的大小分组,按组同时完成。但是 file 模块还需单独讨论,比如读文件时它需要等 HD 硬盘返回数据,所以 file 任务会先占用一个 thread,请求 HD 数据,如果还有正在等待 thread 的任务,file 就需要让出 thread,最后等 threadpool 里有空闲 thread 时再拿回 thread,反而会显得「被堵塞」了。此时增加 threadpool_size 能提升读文件的完成时间。
而对于 HTTPS 模块而言,它不走 threadpool,直接交由 OS 管理,所以速度是最快的。
Node 官方文档里也有详尽的介绍:
https://nodejs.org/en/docs/guides/dont-block-the-event-loop/
https://nodejs.org/en/docs/guides/
Improving Node Performance
-> 为了解决多个请求进来时,Event loop 里的 Single Thread 堵塞问题
- Use Node in 'Cluster' Mode
Clustering in Theory: Cluster Manager: Start multiple Instances of Node Server
通过 cluster.isMaster 可以判断这份 node 是运行在 Cluster Manager里的,还是普通的 Worker Instance里的
if(cluster.isMaster) {cluster.fork()} else {//do the work}
A: 那是不是 fork 越多 children 越好呢?
Q: 不是的,如果 children 太多,CPU 就需要(bounce around)并发处理这些任务,比方说正常情况下1s一个的任务,6个任务的完成时间对于单核CPU会需要6s,对于双核可能需要3s。而不是说6个任务都可以1s就完成并返回。-----> so cluster.fork()的个数最好和cpu核数(无论是 physical 的还是logical 的, logical的 = physical*单个的thread数)保持一致
==》pm2 start index.js -i 0: means that let pm2 to decide the number of cluster
- Use Worker Threads
const { Worker } = require('worker_threads');
(nodejs里的很多任务都由libuv放在Worker里完成的)
不过作者的意见是这个远不如 cluster 有用