Процесс с привязкой к процессору блокирует рабочий пул при использовании дочернего процесса на HTTP-сервере NestJS - PullRequest
0 голосов
/ 20 ноября 2018

Версия узла: v10.13.0

Я пытаюсь провести очень простой тест на параллелизм запросов NodeJS, связанный с интенсивным вычислением ЦП.Я понимаю, что NodeJS - не лучший инструмент для процессов, связанных с процессором, и что дочерний процесс не должен порождаться систематически , но этот код предназначен для тестирования работы дочерних процессов.Также это написано на TypeScript с использованием NestJS.

src / app.controller.ts

import { Get, Param, Controller } from '@nestjs/common';
import fork = require('child_process');

@Controller()
export class AppController {
  @Get()
  async root(): Promise<string> {
    let promise = new Promise<string>(
        (resolve, reject) => {
          // spawn new child process
          const process = fork.fork('./src/cpu-intensive.ts');
          process.on('message', (message) => {
            // when process finished, resolve
            resolve( message.result);
          });
          process.send({});    
        }
    );    
    return await promise;
  }
}

src / cpu -енсивный.ts

process.on('message', async (message) => {
  // simulates a 10s-long process
  let now = new Date().getTime();
  let waittime = 10000; // 10 seconds
  while (new Date().getTime() < now + waittime) { /* do nothing */ };
  // send response to master process
  process.send({ result: 'Process ended' });
});

Такой длинный процесс, , если он выполняется без запуска новых дочерних процессов, приводит к этой временной шкале результатов с 5 одновременными запросами (отмеченными от # 1 до # 5).Каждый процесс, блокирующий событие цикла, каждый запрос должен ждать завершения предыдущих запросов.

Time 0    10   20   30   40   50
#1   +----+
#2   +----+----+
#3   +----+----+----+
#4   +----+----+----+----+
#5   +----+----+----+----+----+

При порождении новых дочерних процессов я ожидал каждый процесс будет обрабатываться одновременно другим логическим ядром на моем процессоре (у моего есть 8 логических ядер), что приведет к этой прогнозируемой временной шкале:

Time 0    10   20   30   40   50
#1   +----+
#2   +----+
#3   +----+
#4   +----+
#5   +----+

Хотя, Я наблюдаю этот странный результат в каждом тесте:

Time 0    10   20   30   40   50
#1   +----+
#2   +----+----+
#3   +----+----+----+
#4   +----+----+----++
#5   +----+----+----+-+

Первые 3 запроса действуют так, как если бы рабочий пул был голодным, хотя я бы предположил, что было бы создано 3 разных пула.Последние 2 запроса очень сбивают с толку, поскольку они действуют как работа одновременно с запросом № 3.

В настоящее время я ищу объяснение:

  • , почему первые 3 запроса не даютне действует так, как если бы он выполнялся одновременно
  • , почему последние 3 запроса действуют так, как если бы они выполнялись одновременно

Обратите внимание, что если я добавлю еще один «быстрый» метод следующим образом:

  @Get('fast')
  async fast(): Promise<string> {
    return 'Fast process ended.';
  }

этот метод не подвержен влиянию процессов, интенсивно использующих процессор, выполняющихся в параллельном режиме, и всегда отвечает мгновенно.

1 Ответ

0 голосов
/ 03 декабря 2018

Я выполнил тестовый пример на своей машине, и он работает нормально. Вы можете проверить это на своей машине.

Версия узла: v8.11.2 ОС: macOs High Sierra 10.13.4, 8 ядер

child-process-test.js

const child_process = require('child_process');  
for(let i=0; i<8; i++) {  
    console.log('Start Child Process:',i,(new Date()));
    let worker_process = child_process.fork("cpu-intensive-child.js", [i]);    
    worker_process.on('close', function (code) {  
        console.log('End Child Process:', i , (new Date()), code);  
    });
}

cpu-интенсивности-child.js

const fs = require('fs');
// simulates a 10s-long process
let now = new Date().getTime();
let waittime = 10000; // 10 seconds
while (new Date().getTime() < now + waittime) { /* do nothing */ };
// send response to master process
// process.send({ result: 'Process ended' });

Выход

enter image description here

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

...