从Node HTTP请求中运行的算法运行时间要长得多

Mar*_*ark 16 javascript algorithm mongoose mongodb node.js

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

使事情变得复杂的是,可以存在多边形,因此我的算法使用多边形包中的来计算点是否在多边形内部,并且如果数据指向的话,那么数据的颜色会不同.

当数据点少于50,000时,此工作正常.但是,当有800,000时,请求大约需要23秒.我已经对代码进行了分析,大部分时间用于遍历所有数据点,并确定在画布上绘制的位置以及颜色(取决于它是否在一个或多个多边形中).这是我制作的一个傻瓜.基本上我做这样的事情:

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
Run Code Online (Sandbox Code Playgroud)

算法本身不是问题.我遇到的问题是,当算法在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秒

Bob*_*ill 2

刚刚完成将代码版本作为 NodeJS 服务运行。该代码是从你的骗子那里获取的。对于 100,000 行数据,执行时间为 171 毫秒(将前 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"));
Run Code Online (Sandbox Code Playgroud)

我将创建 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]);
Run Code Online (Sandbox Code Playgroud)

然后运行你的代码:

  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);
Run Code Online (Sandbox Code Playgroud)

结果是 171 毫秒。