Алгоритм запускается из 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 мсек.