Node.Js Windows 中的线程池

Node.Js Threadpool in Windows

所以我的理解是,任何阻塞的文件系统操作(例如fs.readFileSync)最终都会委托给线程池中的线程之一,以保持事件循环空闲。现在,我 运行 来自 windows 的应用程序和我正在使用的命令 set UV_THREADPOOL_SIZE=4 & node index.js

下面是我的示例代码,

const start = new Date().getTime();
readFile();
readFile();
readFile();
readFile();
readFile();

function readFile() {
  fs.readFileSync('./content/1.txt');
  const end = new Date().getTime();
  console.log('Time took: ', (end - start) / 1000);
}

现在无论我将线程池大小设置为一个还是四个,执行时间都几乎相同。仅供参考,我的 PC 中有 两个 CPU 核心 。因此,我的期望是,如果我在读取文件的 5 个函数调用中将线程池大小设置为 4(或让默认设置起作用),那么说前四个需要 x 秒(我知道这不是确切的时间两者都调用但会非常接近),然后是最后一个 (x+n),其中 x 和 n 是随机数并表示以秒为单位的时间差。

但这并没有发生。无论线程池调用的数量如何,都需要花费相同的时间来完成并且一个接一个地完成。

所以,看来我对 node.js 线程池如何工作的理解是不正确的。任何帮助,将不胜感激。谢谢。

第一个问题是您正在使用 fs.readFileSync()。这意味着您的文件操作一次只会被请求一个。在第一个完成之前,第二个不会开始。这与线程池无关。这是因为您正在使用 readFile() 的阻塞同步版本。 JS 解释器将被阻塞,直到第一个 fs.readFileSync() 完成,第二个只在第一个完成后才开始,依此类推。因此,因此,在这种情况下,有多少线程为文件系统提供服务并不重要。

如果你想在文件操作中使用多个线程,你需要使用像fs.readFile()这样的异步文件操作,这样你就可以同时进行多个文件操作,从而拥有更多有机会使用多个线程。

另外,同一个磁盘上的文件操作不像其他类型的操作那样具有多个 threads/CPUs 的可扩展性,因为 read/write 磁头一次只能在一个地方,所以即使您确实更改了代码以成功使用多个线程或 CPU 由于 read/write 头位置的序列化,您无法在同一驱动器上获得完全并行的文件访问。

下面是一个使用异步 fs.readFile() 的测试示例:

const start = new Date().getTime();
let cntr = 0;

readFile(0);
readFile(1);
readFile(2);
readFile(3);
readFile(4);

function readFile(i) {
  fs.readFile('./content/1.txt', function(err, data) {
      if (err) {
          console.log(err);
          return;
      }
      const end = new Date().getTime();
      console.log(`Time took: ${i} ${(end - start) / 1000}`)
      if (++cntr === 5) {
          console.log(`All Done. Total time: ${(end - start) / 1000)}`;
      }
  });
}

如果您每次调用 readFile() 时读取不同的文件(不在 OS 文件缓存中),此测试可能会更有意义。因为它是 2-5 个请求,可能只是从 OS 文件缓存中的内存中获取数据,而不是实际访问磁盘。