Алгоритм запускается из Node HTTP-запроса занимает гораздо больше времени для запуска

У меня есть приложение node, которое отображает данные на графике графика x, y dot. В настоящее время я делаю запрос GET с передней стороны, а мой сервер back node принимает запросы, перебирает массив точек данных, рисует холст с помощью Node Canvas и передает его обратно в интерфейс, где он отображается как изображение PNG.

Усложнение состоит в том, что могут быть многоугольники, поэтому мой алгоритм вычисляет, находится ли точка внутри многоугольника, используя point in polygon package, и цвета, которые данные указывают по-разному, если они есть.

Это работает отлично, когда имеется менее 50 000 точек данных. Однако, когда есть 800 000, запрос занимает приблизительно 23 секунды. Я профилировал код, и большая часть времени тратится на все точки данных и вычисляет, где его запечатлеть на холсте и какой цвет (в зависимости от того, находится ли он в одном или нескольких полигонах). Здесь сделан plunker. В основном я делаю что-то вроде этого:

for (var i = 0; i < data.length; i++) {

  // get raw points
  x = data[i][0];
  y = data[i][1];

  // convert to a point on canvas
  pointX = getPointOnCanvas(x);
  pointY = getPointOnCanvas(y, 'y');

  color = getColorOfCell(pointX, pointY);

  color = color;

  plotColor.push({
      color: color,
      pointX: pointX,
      pointY : pointY
  });

}

// draw the dots down here

Сам алгоритм не является проблемой. Проблема заключается в том, что когда алгоритм запускается в HTTP-запросе, для вычисления того, какой цвет имеет смысл, требуется около 16 секунд. Но если сделать это в хроме на лицевой стороне, это займет чуть больше секунды (см. Плункер). Когда я запускаю алгоритм в командной строке с Node, это занимает менее секунды. Таким образом, факт, что мое приложение запускает алгоритм в HTTP-запросе, замедляет его массово. Итак, пара вопросов:

Зачем это было? Почему выполнение алгоритма из HTTP-запроса занимает намного больше времени?

Что я могу сделать, чтобы исправить это, если что? Как-то можно было бы сделать запрос для запуска задачи, а затем уведомить интерфейс, когда закончите и получите PNG?

ИЗМЕНИТЬ Я полностью протестировал запуск алгоритма и создание PNG через командную строку. Это намного быстрее, менее чем за полсекунды, чтобы определить, какой цвет должен составлять каждый из 800-кратных точек данных. Im думая использовать сокет для того чтобы сделать запрос к серверу и начать задачу, после этого возвратите изображение. Я сбив с толку, но почему код должен занимать так много времени, когда выполняется в HTTP-запросе...

ИЗМЕНИТЬ Проблема - Монго и Мангуста. Я сохраняю координаты каждого многоугольника в Монго. Я беру эти координаты один раз, но когда я сравниваю их с каждой x, y point/. Так или иначе, это то, что массово задерживает алгоритм. Если я закрою документ Mongo, алгоритм будет идти от 16 секунд до 1,5 секунд......

Edit @DevDig указал на основную проблему в разделе комментариев - при использовании объекта Mongoose существует множество геттеров и сеттеров, замедляющих его. Использование lean() в запросе уменьшает алгоритм с 16 секунд до 1,5 секунд

Ответы

Ответ 1

Только что закончил запуск версии вашего кода в качестве службы nodeJS. Код берется из вашего плункера. Время выполнения составляло 171 мсек для 100 000 строк в данных (реплицированные первые 10K строк в 10 раз. Вот что я сделал:

Во-первых, ваши файлы data.json и gates.json на самом деле не являются файлами JSON, это файлы javascript. Я удалил инструкции var data/gates = с фронта и удалил точку с запятой. Проблема, с которой вы сталкиваетесь, может иметь отношение к тому, как вы читаете в своих наборах данных в своем приложении. Поскольку вы не изменяете ворота или данные, я читаю их как часть настройки на сервере, именно так вы обрабатываете браузер. Если вам нужно читать файлы в каждый раз, когда вы обращаетесь к серверу, то это, конечно, изменит время. Это изменение потребовало времени выполнения от 171 мсек до 515 мсек - все еще ничего похожего на то, что вы видите. Это выполняется на MacBook Pro. При необходимости я могу обновить тайминги с сервера облачного доступа к сети.

получение файлов:

 var fs = require("fs");
 var path = require("path");
 var data = [];
 var allGatesChain;
 var events = [];
 var x, y, pointX, pointY;

 var filename = __dirname + "/data.txt";

 data = JSON.parse(fs.readFileSync(filename, "utf-8"));
 filename = __dirname + "/gates.json";
 var gates = JSON.parse(fs.readFileSync(filename, "utf-8"));

Я переместил ваши подпрограммы, чтобы создать allGatesChain и события в экспортируемой функции:

  allGatesChain = getAllGatesChain();
  generateData();
  console.log("events is "+events.length+" elements long. events[0] is: "+events[0]);
  console.log("data is "+data.length+" elements long. data[0] is "+data[0]);

а затем запустил ваш код:

  var start, end;
  var plotColor = [];
  start = new Date().getTime();
  for (var i = 0; i < data.length; i++) {
    // get raw points
    x = data[i][0];
    y = data[i][1];
    // convert to a point on canvas
    pointX = getPointOnCanvas(x);
    pointY = getPointOnCanvas(y, 'y');
    color = getColorOfCell({
      gateChain: allGatesChain,
      events: events,
      i: i
    });
    color = color;
    plotColor.push({
        color: color,
        pointX: pointX,
        pointY : pointY
    });
  }
  end = new Date().getTime();
  var _str = "loop execution took: "+(end-start)+" milliseconds.";
  console.log(_str);
  res.send(_str);
Результат

составил 171 мсек.