Как обрабатывать сбои, связанные с выделением памяти в nodejs? - PullRequest
0 голосов
/ 28 марта 2020

Я пытаюсь заполнить базу данных mongoDB случайными данными из фейера. Поэтому я использовал функцию setInterval для многократного выполнения запроса к базе данных, но проблема в том, что когда я отслеживаю использование моей памяти, оно только растет и растет, пока не достигнет того предела механизма v8, независимо от того, насколько я увеличу лимиты, которые он дает сбой. В любом случае, это лишь вопрос времени.

const faker = require("faker")
let userName; 
let email; 

setInterval(async () => {
  userName = faker.name.findName(); 
  email = faker.internet.email(); 
  await User.create({
    userName: userName,
    email: email,
  })
    .then(() => {
      //getting memory usage
      console.log(process.memoryUsage().heapUsed / 1024 / 1024);
    })
    .catch(err => {
      console.log(err);
    });
});

Как мне управлять распределением памяти, чтобы остановить сбои? это считается утечкой памяти?

1 Ответ

1 голос
/ 28 марта 2020

Вызов setInterval без времени, это добавляет в очередь обратного вызова как можно быстрее, без каких-либо ограничений. И если вы добавляете элементы в очередь быстрее, чем можете их удалить, память всегда будет расти.

* Редактировать: чтобы точно понять, что происходит с событием l oop и очередью обратного вызова при выполнении setInterval, Я рекомендую посмотреть отличные выступления JSConf Филипом Робертсом и / или Джейком Арчибальдом .

У вас есть несколько вариантов. Вы можете изменить на setTimeout, а затем вызвать еще один setTimeout в вашем .then после завершения последнего вызова. Это, по сути, сериализовало бы его.

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

const faker = require("faker")
let userName; 
let email; 
let numRunning = 0;
let maxRunning = 10;

setInterval(async () => {
  if (numRunning > maxRunning) return;
  numRunning++;
  userName = faker.name.findName(); 
  email = faker.internet.email(); 
  await User.create({
    userName: createdUser.userName,
    age: createdUser.age,
  })
    .then(() => {
      numRunning--;
      //getting memory usage
      console.log(process.memoryUsage().heapUsed / 1024 / 1024);
    })
    .catch(err => {
      numRunning--;
      console.log(err);
    });
}, 50);

Я также добавил интервал в 50 мс. Ноль для setInterval действительно не очень хорошая идея. Есть веские причины иногда использовать ноль для setTimeout, но я не могу придумать вескую причину использовать ноль для setInterval.

...