请求一次,耗时100ms左右。
请求10次,每个耗时1100ms左右。为什么不是第一组四个耗时100ms,第二组四个耗时200ms,最后一组耗时300ms。线程池默认是四个,一次可以处理四个IO请求,然后后面的IO等待线程空闲了再执行。为啥不是这样的呢
请求一次,耗时100ms左右。
请求10次,每个耗时1100ms左右。为什么不是第一组四个耗时100ms,第二组四个耗时200ms,最后一组耗时300ms。线程池默认是四个,一次可以处理四个IO请求,然后后面的IO等待线程空闲了再执行。为啥不是这样的呢
谢邀。
这目前不是一条回答,只是罗列了一些可能涉及到的点,背后的原因我晚点查查资料看看能不能找到。
首先,如果我没记错的话,异步的 fs
API 会进 thread pool 应该没什么疑问。然后 thread pool 目前的默认值是 4 应该也是对的。
接下来,nodejs 的 event loop 中,poll 阶段负责处理 I/O event 应该也是没什么问题的。然后对应的 callback 应该也是在这个阶段执行。这个阶段会 block 整个 event loop。最长的 block 时间我记不清了,可能需要查一下资料。
然后为了避免是读同一个文件的问题,我生成了很多个一样的 150M 的文件。同样循环去读,下面是例子用到的代码:
const fs = require('fs');
const COUNT = 16;
for (let i = 1; i <= COUNT; ++i) {
console.time(i);
console.log(process.hrtime());
fs.readFile(`a${i}`, (err, data) => {
console.log(process.hrtime());
console.timeEnd(i);
});
}
执行的时候通过环境变量设置 thread pool size 为 1,UV_THREADPOOL_SIZE=1
。然后会发现这个 COUNT
不管设置多少,callback 们的时间都是差不多的。例如我尝试了 128,这时候每个 callback 里面的时间都是 4s 多了,我猜是已经超过了上文提到的 poll 阶段的最大 block 时间。
然后就比较奇怪了,目前 pool size 是 1,但是还是所有的 callback 一起触发。如果中间有 poll 阶段(毕竟已经 4s 多了,不过我晚点查一下资料再确认一下),并且有已经完成的读取,那么 callback 应该会被触发才对吧。
不知道是不是我的理解出了什么问题,晚点再更新,TODO。
我还是没有找到相关的资料。我在 stackoverflow 上提问求助了,不过似乎还没得到靠谱的答案。具体问题在这里。
其中有人提到了 node 在读多个文件的时候,那些小的 chunk 会被穿插执行,所以看起来像是多个文件一起在读。不过我觉得既然 poll size 只有 1,应该不是在同时读多个文件才对。
我继续问问朋友。持续关注,如果题主有答案了也欢迎告诉我。
我这边mac是一批一批的出来的:
TedMacdeMacBook-Pro:nodecpu100 tedmac$ node app.js
Example app listening on port 3002!
node已接受到请求--id 1
node已接受到请求--id 2
node已接受到请求--id 3
node已接受到请求--id 4
node已接受到请求--id 5
node已接受到请求--id 6
异步读取完成
node已接受到请求--id 7
异步读取完成
node已接受到请求--id 8
异步读取完成
node已接受到请求--id 9
异步读取完成
异步读取完成
异步读取完成
异步读取完成
8 回答4.6k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
5 回答6.3k 阅读✓ 已解决
4 回答2.2k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.4k 阅读✓ 已解决
你定义的线程池有4个,但实际上线程的执行还受上层进程执行的影响,进程执行又受系统进程管理的影响,这造成线程资源分配不一定是你预想的那么平均、均衡。