使用高数字时,功能会变慢

时间:2015-11-02 19:20:45

标签: javascript performance loops average

我写了一个脚本,而不是给出一组数据的真实平均值,而是返回包含大多数数据点的窗口。让我展示一些代码:

time.tic()
var selectedAverage = 0;
var highestPointCount = 0;
for (var i = 1; (i*step) <= maxValue; i++) {
    var dataPointCount = 0;
    for (var j = 0; j < myArray.length; j++) {
        if (myArray[j] >= minValue+(i-1)*step && myArray[j] <= minValue+i*step) {
            dataPointCount++;
        }
    }
    if (dataPointCount > highestPointCount) {
        highestPointCount = dataPointCount;
        selectedAverage = (minValue+(i-1)*step)+Math.round(0.5*step);
    }
}
console.log(time.toct().ms) 
return selectedAverage;

首先,通过从最大值中减去最小值然后再确定10来计算步长值。因此,存在10个“水平”窗口。然后脚本计算每个窗口中的数据点数量并返回适当的平均值。

然而,当传入较大数字的数组(例如1.000.000)时,脚本似乎极度减速(有时超过200次)。数组长度大约为200但总长度相同,因此必须与实际值相关联。知道哪里出错了?

编辑: 获取步长值的代码:

var minValue = myArray.min();
var maxValue = myArray.max();
var step = Math.round((maxValue-minValue)/10);
if (step === 0) {
    step = 1
}

.min()和.max()是附加到Array的原型。但这一切都非常快。我已经测量了每一步,它是for循环减速。

2 个答案:

答案 0 :(得分:1)

我认为你的问题有两个不同的地方:

  1. 删除了不必要/重复的计算
  2. 在嵌套代码中,您每次都会minValue+(i-1)*stepminValue+i*step计算相同的minValueistep值。 你应该在第二个for循环之前把它拉起来:

    var dataPointCount = 0;
    var lowerLimit = minValue+(i-1)*step;
    var higherLimit = minValue+1*step;
    for (var j = 0; j < myArray.length; j++) {
        if (myArray[j] >= lowerLimit && myArray[j] <= higherLimit) {
            dataPointCount++;
        }
    }
    
    1. 当您处理大数据阵列时可能会因内存交换而导致严重的性能损失。从您的角度来看,您正在处理单个数组实例,但是当您拥有如此庞大的数组时,JavaScript VM不可能访问连续的内存空间来保存所有这些值。很可能JavaScript VM必须处理从操作系统获取的多个内存块,并且必须花费额外的努力来翻译读/写期间的值。

答案 1 :(得分:1)

如果我正确理解你的算法,这应该删除所有不必要的计算并且要快得多:

var arr = [];
var maxQty=0;
var wantedAverage = 0;
for (var j = 0; j < 11; j++) {
    arr[j]=0;
}
for (var j = 0; j < myArray.length; j++) {
    var stepIndex = Math.floor((myArray[j]-minValue)/step)
    arr[stepIndex]+=1;

    if(arr[stepIndex] > maxQty ){
        wantedAverage = minValue + stepIndex*step +Math.round(0.5*step);
        maxQty = arr[stepIndex]
    }
}
console.log(maxQty, wantedAverage)

我们只迭代数组的每个元素一次,并计算它所属的窗口的索引,向数量数组添加一个。然后,如果我们在找到的窗口中有更多的点数,我们会更新wantedAverage