我编写了以下node.js程序(Ubuntu 14.04上的节点版本6.2.0),以了解有关node.js中libuv threadpool的更多信息。在程序中,我正在阅读两个大小为10KB的文本文件。成功读取文件后,我正在做一些计算密集型任务(在回调中)。
var log4js = require('log4js');// For logging output with timestamp
var logger = log4js.getLogger();
var fs=require('fs');
fs.readFile('testFile0.txt',function(err,data){//read testFile0.txt
logger.debug('data read of testFile0.txt');
for(var i=0; i<10000; i++)//Computing intensive task. Looping for 10^10 times
{
for(var j=0; j<10000; j++)
{
for(var k=0; k<100; k++)
{
}
}
}
});
fs.readFile('testFile1.txt',function(err,data){//read testFile1.txt
logger.debug('data read of testFile1.txt');
for(var i=0; i<10000; i++)//Computing intensive task. Looping for 10^10 times
{
for(var j=0; j<10000; j++)
{
for(var k=0; k<100; k++)
{
}
}
}
});
根据我对libuv线程池的理解,应立即读取这两个文件,并打印语句&#34;读取testFile0.txt&#34;,#34;读取testFile1的数据之间的时间差。 TXT&#34;因为默认线程池大小为4并且只有两个异步请求(文件读取操作),所以应该非常少(以毫秒或最多为单位)。但是,语句的打印时间差异&#34; testFile0.txt&#34; && 34; testFile0.txt&#34;的数据读取相当大(10秒)。有人可以解释为什么时差如此之大?在回调中完成的计算密集型任务是否会导致较大的时间差?
答案 0 :(得分:2)
libuv有一个大小为4的线程池(默认情况下),因此该部分是正确的。现在,让我们看看它是如何实际使用的。
当某个操作在线程池中排队时,它会在其中一个线程上运行,然后将结果发布到&#34; main&#34;线程,它是循环运行的线程。结果以FIFO样式处理。
在您的情况下,读取文件并行发生,但处理结果将被序列化。这意味着虽然并行地从磁盘读取字节,但回调将始终一个接一个地运行。
你看到了延迟,因为第二个回调只能在第一个回调完成后运行,但需要大约10秒,因此延迟。
使这个完全平行的一种方法是在线程池本身进行计算,尽管你需要一个使用uv_queue_work或使用child_process mdoule的插件。 / p>