потоки libuv выполняются последовательно в nodejs - PullRequest
0 голосов
/ 27 февраля 2020

Итак, я выполнял этот код, чтобы проверить количество потоков в пуле потоков, созданных библиотекой libuv -

var fs = require('fs');
var util = require('util');
var sleep = require('sleep');
var start = process.hrtime();

var sample_func = function(callback) {
  var i = 0;
  sleep.sleep(1);
  callback();
}
for (var i = 0; i < 6; ++i) {
  (function (id) {
    sample_func(function () {
      var end = process.hrtime(start);
      console.log(util.format('sample func %d finished in %ds', id, end[0] + end[1] / 1e9));
    });
  })(i);
}

Поскольку libuv по умолчанию создает 4 потока в пуле потоков, а моя функция-пример асинхронная, я был ожидая, что этот вывод будет напечатан в моей консоли -

sample func 0 finished in 1.003170344s
sample func 1 finished in 1.052704191s
sample func 2 finished in 1.058100525s
sample func 3 finished in 1.060514229s
sample func 4 finished in 2.003446385s
sample func 5 finished in 2.007682862s

Таким образом, первые 4 итерации выполняются параллельно, а последние 2 должны ждать, пока первые 4 завершатся sh. Однако, я получил следующее:

sample func 0 finished in 1.00095422s
sample func 1 finished in 2.056155718s
sample func 2 finished in 3.058480649s
sample func 3 finished in 4.061336076s
sample func 4 finished in 5.063556904s
sample func 5 finished in 6.066219487s

Это означает, что каждая итерация выполняется одна за другой, занимая в общей сложности 6 секунд. Кто-нибудь может мне помочь здесь, почему это происходит?

PS: я напечатал значение process.env.UV_THREADPOOL_SIZE, я получил неопределенное значение; версия узла: v12.9.1

Спасибо

1 Ответ

1 голос
/ 27 февраля 2020

Nodejs Событие l oop (реализовано в Libuv) выполняется в одном потоке (основной поток). Код блокировки (в вашем случае sleep ()) выполняется в основном потоке. Сетевые, файловые и DNS операции ввода-вывода выполняются асинхронно с помощью Libuv. Nodejs используется следующая схема:

API-интерфейсы асинхронной системы используются Node.js везде, где это возможно, но там, где их нет, пул потоков libuv используется для создания API-интерфейсов асинхронных узлов на основе синхронной системы. API. Node.js API, которые используют пул потоков:

  • все API-интерфейсы fs, кроме API-интерфейсов наблюдателя файлов и те, которые:
  • явно синхронные асинхронные API-интерфейсы шифрования, такие как crypto. pbkdf2 (), crypto.scrypt (), crypto.randomBytes (), crypto.randomFill (), crypto.generateKeyPair ()
  • dns.lookup () все API-интерфейсы zlib *, кроме явно синхронных .

Теперь вернемся к вашей проблеме, sleep.sleep(1); событие функционального блока l oop (основной поток) в течение 1 секунды, как говорится в документации sleep. Вот почему ваша функция работает синхронно.

...