数百个坐标之间的Nodejs距离计算阻塞了我的服务器

Posted

技术标签:

【中文标题】数百个坐标之间的Nodejs距离计算阻塞了我的服务器【英文标题】:Nodejs distance calculation between hundreds of coordinates is blocking my server 【发布时间】:2015-08-20 08:39:06 【问题描述】:

我有数百个坐标(纬度、经度)的列表。 对于每个客户请求,我需要计算每对这些点之间的距离。 对于 1,000 个坐标的列表 - 我需要 500 毫秒才能做到这一点,所以它阻塞了我的 nodejs 服务器。 如何通过使其异步来“解决”这个问题?我不希望它阻塞我的服务器,以便它可以继续处理其他请求..

是否建议打开另一个nodejs进程并使其成为“距离计算服务”或类似的东西?

这是一个示例测试代码:

var pts=[];
for (i=0;i<1000;i++)
    pts.push(randomLatLon());

var a;
var b;
var i,j;
var start = new Date();
for (i=0;i<pts.length;i++)
    for (j=0;j<pts.length;j++)
        if (i===j) 
            continue;
        
        a = pts[i];
        b = pts[j];
        var dist = utils.getDistance(a.lat,a.lon,b.lat,b.lon);
    

console.log('total time',new Date()-start,'ms'); // ~500 ms

这里是 utils.getDistance 函数:

E.getDistance = function(lat1,lon1,lat2,lon2) 
  var R = 6371*1000; // Radius of the earth in m
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in m
  return d;

【问题讨论】:

你应该看看 process.nextTick() 函数。我不确定它能否解决您的问题,但这是我将尝试的第一首曲目。 它仍然会阻塞服务器 500 毫秒,无论哪种方式.. 它只会将阻塞延迟到下一个滴答声.. 没有额外的、专门的 nodejs 服务器来完成这个任务,这是一个更好的选择? 如果您将代码重构为每处理 100 或 500 距离执行 process.nextTick,则不会。 不错的方法。所以我假设每处理 100 个距离后,节点的 process.nextTick 将使节点可用于其他请求,因此只会在计算 100 个距离所需的一小段时间内被阻塞。我会尝试的。但是仍然-在单独的小型nodejs本地网络服务器中进行此计算距离不是更简单(更快)吗?两个nodejs进程之间没有共享资源,所以我看不到它有任何问题 【参考方案1】:

这在一定程度上取决于您需要对结果做什么。您是否需要一系列距离作为输出?

一种方法是使用诸如 Q 之类的 Promise 将每个计算变成一个单独的操作,然后使用 Q.all 等待所有计算完成,但是对于 1000x1000 这样做可能不是一个好主意,因为您将不得不在内存中保留一个包含 50 万个承诺的数组。根据您需要对输出执行的操作以及原始点数组的大小,按顺序调用每个计算可能会更好,也可能不会更好。一种方法是使用递归:

function calculateDistances(pts) 
    var start = new Date();
    calculateNextDistance(pts, 0, 1).then(function() 
        console.log('total time',new Date()-start,'ms');
    );

    function calculateNextDistance(pts, i, j) 
        return Q().then(function () 
            var a = pts[i];
            var b = pts[j];
            var dist = utils.getDistance(a.lat, a.lon, b.lat, b.lon);

            j++;

            if (j == pts.length) 
                i++;
                j = i + 1;
            

            if (j < pts.length) 
                return calculateNextDistance(pts, i, j);
            
        );
    

这似乎对我很有效,但请注意,由于所有上下文切换,现在完成计算当然可能需要比 500 毫秒更长的时间。一种折衷方案可能是在每次迭代中进行一些计算。

(顺便说一句,您可以通过不计算 x->y AND y->x 来消除很多计算,这意味着循环可以转到 for (j=i+1;j&lt;pts.length;j++),我在上面的代码中也使用了它)

生成一个我不知道的子进程是否更好,这可能值得一试。

【讨论】:

以上是关于数百个坐标之间的Nodejs距离计算阻塞了我的服务器的主要内容,如果未能解决你的问题,请参考以下文章

使用数百个航点生成最有效的路线

快速方法按距离搜索数百万个坐标

计算两个纬度和经度坐标之间的距离

计算当前坐标和坐标列表之间的距离

在 Visual Studio 中运行代码时出现数百个构建错误

高德地图计算两坐标之间距离