我有一个包含数百个坐标(lat,lon)的列表。 对于每个客户端请求,我需要计算每对这些点之间的距离。 对于1000个坐标的列表 - 我需要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;
}
答案 0 :(得分: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-&gt; y和y-&gt; x来消除相当多的计算,这意味着循环可以for (j=i+1;j<pts.length;j++)
,我也在上面的代码中使用了1}
不管是否最好生成一个我不知道的子进程,它可能值得尝试。