Утечка памяти в Node.js при использовании jsdom для десериализации JSON в DOM - PullRequest
0 голосов
/ 07 января 2019

Мы используем jsdom , чтобы преобразовать пользовательский json, описывающий документ, в документ jsdom, чтобы мы могли использовать селекторы css для легкого изменения документа.

Из-за проблем наш сервер теряет память и периодически сталкивается с OOME. Анализ приводит нас к тому факту, что виновным является jsdom.

В настоящее время мы задаемся вопросом, неправильно ли мы используем jsdom. Если мы не сможем решить эту проблему, мы попробуем cheerio вместо jsdom, что приводит к большим усилиям из-за рефакторинга и тестирования.

Снимки кучи, которые я сделал, показали, что ни один из объектов JSDOM не собирается GC. Это означает, что после двух запусков в снимке есть два объекта JSDOM, а после 10 запусков - 10 объектов.

Я пытался выставить GC для принудительного сбора мусора. Это не помогло.

Я попытался использовать window.close () после десериализации, но это тоже не помогло.

В настоящее время мы используем jsdom примерно следующим образом:

let document = new JSDOM('<!DOCTYPE html>').window.document;
// json is the json to be deserialized
deserializeJsonNode(json);

function deserializeJsonNode(node_data, parent_node) {
  if (node_data === null) {
    return null;
  }
  let node;
  switch (node_data.nT) {
    case Node.COMMENT_NODE:
      node = document.createComment(node_data.attribute);
      break;
    case Node.TEXT_NODE:
      node = document.createTextNode(node_data.attribute);
      break;
    case Node.DOCUMENT_TYPE_NODE:
      node = document.implementation.createDocumentType(node_data.attribute);
      break;
    case Node.ELEMENT_NODE:
      node = document.createElement(node_data.attribute);
      break;
    case Node.DOCUMENT_NODE:
      node = document;
      break;
  }

  if (parent_node) {
    parent_node.appendChild(node);
  }

  var child_nodes = node_data.attribute;
  if (child_nodes) {
    child_nodes.forEach(child_node_data => {
      deserializeJsonNode(child_node_data, node);
    });
  }
  return node;
}

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

Заранее спасибо.

1 Ответ

0 голосов
/ 16 января 2019

после дальнейшего анализа мы обнаружили, что проблема возникла намного раньше в нашей программе. Мы использовали драйвер Node.js для Cassandra с версией 3.1 и впоследствии передавали полученные данные в JSDOM посредством обратного вызова.

Кажется, ошибка возникла из-за этого. После обновления до версии 3.2 драйвера Cassandra и синхронного получения данных ошибка исчезла.

...