Правильно ли я понимаю libuv threadpool в node.js?

Я написал следующую программу node.js (версия узла 6.2.0 в Ubuntu 14.04), чтобы больше узнать о пуле потоков libuv в node.js. В программе я читаю два текстовых файла размером 10 КБ. После того, как файлы успешно прочитаны, я выполняю некоторую вычислительную задачу (в обратном вызове).

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 threadpool, два файла должны быть прочитаны немедленно, а разница во времени между печатью операторов «чтение данных из testFile0.txt», «чтение данных из testFile1.txt» должно быть очень меньше (в миллисекундах или самое большее второе), поскольку размер пула потоков по умолчанию равен 4 и имеется только два асинхронных запроса (операция чтения файла). Но разница во времени между печатью операторов «чтение данных из testFile0.txt» и «чтение данных из testFile0.txt» довольно велико (10 секунд). Кто-нибудь может объяснить, почему такая большая разница во времени?? Способствует ли интенсивная вычислительная задача, выполняемая в обратном вызове, большой разнице во времени??


person Sunkavilli Ravi Chaitanya    schedule 21.05.2016    source источник


Ответы (1)


libuv имеет пул потоков размером 4 (по умолчанию), так что эта часть верна. Теперь давайте посмотрим, как это на самом деле используется.

Когда какая-то операция ставится в очередь в пуле потоков, она выполняется в одном из потоков, а затем результат отправляется в «основной» поток, который является потоком, в котором выполняется цикл. Результаты обрабатываются в стиле FIFO.

В вашем случае чтение файлов происходит параллельно, но обработка результатов будет сериализована. Это означает, что пока байты считываются с диска параллельно, обратные вызовы всегда будут выполняться один за другим.

Вы видите задержку, потому что второй обратный вызов может выполняться только после завершения первого, но это занимает ~ 10 секунд, отсюда и задержка.

Одним из способов сделать это по-настоящему параллельным было бы выполнение вычислений в самом пуле потоков, хотя вам понадобится дополнение для того, что использует uv_queue_work или используйте child_process mdoule.

person saghul    schedule 22.05.2016