从Node HTTP请求中运行的算法运行

时间:2017-06-02 12:53:26

标签: javascript node.js mongodb algorithm mongoose

我有一个节点应用程序,它在x,y点图表上绘制数据。目前,我从前端发出GET请求,我的后端节点服务器接受请求,循环遍历数据点数组,使用Node Canvas绘制画布并将其流回到前端,在那里显示为PNG图片。

复杂的是,可以有多边形,所以我的算法使用point in polygon包来计算一个点是否在多边形内部,并且如果数据指向的话,那么数据的颜色会有所不同。

当数据点少于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秒。但是如果在前端镀铬,那就需要一秒钟(参见plunker)。当我在命令行上使用Node运行算法时,只需不到一秒钟。因此,我的应用程序在HTTP请求中运行算法的事实正在大幅减慢它的速度。所以有几个问题:

为什么会这样?为什么在HTTP请求中运行算法需要更长时间?

如果有的话,我该怎么做才能解决这个问题?是否有可能提出启动任务的请求,然后在完成后通知前端并检索PNG?

修改 我完全测试了运行算法并通过命令行创建PNG。它可以更快,不到半秒就可以计算出每个800k数据点应该是什么颜色。我想使用套接字向服务器发出请求并启动任务,然后让它返回图像。我很困惑,为什么代码在HTTP请求中运行时需要这么长时间......

修改 问题是Mongo和Mongoose。我将每个多边形的坐标存储在Mongo中。我获取这些坐标一次,但当我将它们与每个x,y点/进行比较时。不知何故,这是大大延迟算法的原因。如果我关闭Mongo文档,算法会从16秒到1.5秒......

修改 @DevDig指出了评论部分中的主要问题 - 当使用Mongoose对象时,有许多getter和setter减慢它的速度。在查询中使用lean()可将算法从16秒减少到1.5秒

1 个答案:

答案 0 :(得分:2)

刚刚完成运行您的代码版本作为nodeJS服务。代码取自您的plunker。对于100,000行数据,执行时间为171毫秒(前10K行复制10次。这就是我所做的:

首先,你的data.json和gates.json文件不是真正的JSON文件,它们是javascript文件。我从前面删除了var data / gates =语句并删除了结尾的分号。您遇到的问题可能与您在应用中阅读数据集的方式有关。由于您不修改门或数据,因此我将其作为服务器设置的一部分进行读取,这正是您在浏览器中处理的方式。如果您每次访问服务器时都需要读取文件,那么当然会改变时间。这一改变使执行时间从171毫秒到515毫秒 - 仍然没有接近你所看到的。这是在macBook Pro上执行的。如果需要,我可以从网络访问的云服务器更新时间。

获取文件:

<%= truncate(this.thing, length: 15, separator: '...') %>

我移动了你的例程,将allGatesChain和事件创建到导出的函数中:

 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 = 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]);

结果是171毫秒。