我是node.js的新手.
我试图将70000个项目插入数组,然后删除所有项目:
var Stopwatch = require("node-stopwatch").Stopwatch;
var stopwatch = Stopwatch.create();
var a = []
stopwatch.start();
for (var i = 1 ; i < 70000 ; i++){
a.push((parseInt(Math.random() * 10000)) + "test");
}
for (var i = 1 ; i < 70000 ; i++){
a.splice(0,1);
}
stopwatch.stop();
console.log("End: " + stopwatch.elapsedMilliseconds + " : " + a.length);Run Code Online (Sandbox Code Playgroud)
它工作正常,输出是:
PS C:\Users\Documents\VSCode> node test.js
End: 51 : 0
Run Code Online (Sandbox Code Playgroud)
但是当我将项目数增加到72000时,结束需要太多时间:
var Stopwatch = require("node-stopwatch").Stopwatch;
var stopwatch = Stopwatch.create();
var a = []
stopwatch.start();
for (var i = 1 ; i < 72000 ; i++){
a.push((parseInt(Math.random() * 10000)) + "test");
}
for (var i = 1 ; i < 72000 ; i++){
a.splice(0,1);
}
stopwatch.stop();
console.log("End: " + stopwatch.elapsedMilliseconds + " : " + a.length);Run Code Online (Sandbox Code Playgroud)
输出是:
End: 9554 : 0
Run Code Online (Sandbox Code Playgroud)
为什么会这样?只增加了2000个项目,但需要花费太多时间.
Node.js版本是:v6.11.3
V8 开发人员在这里。在开始( at array[0])删除(或插入)数组元素通常非常昂贵,因为必须移动所有剩余的元素。从本质上讲,对于这些.splice(0, 1)操作中的每一项,引擎必须在引擎盖下做的是:
for (var j = 0; j < a.length - 1; j++) {
a[j] = a[j+1];
}
a.length = a.length - 1`
Run Code Online (Sandbox Code Playgroud)
在某些情况下,V8 可以在引擎盖下使用一个技巧,而不是移动对象的开头——在快速的情况下,你可以看到这个技巧提供的惊人的加速。但是,由于技术原因,此技巧不能应用于超过特定大小的数组。由此产生的“减速”实际上是这种非常昂贵的操作的“真实”速度。
如果您想快速删除数组元素,请从末尾(at array[array.length - 1])删除它们,例如使用Array.pop(). 如果您想一次性删除所有元素,只需设置array.length = 0. 如果您需要快速 FIFO/“队列”语义,请考虑从环形缓冲区中获取灵感:为要读取/返回的下一个元素设置一个“光标”,并且仅在有大量元素要释放时才缩小数组。大致:
function Queue() {
this.enqueue = function(x) {
this.array_.push(x);
}
this.dequeue = function() {
var x = this.array_[this.cursor_++];
// Free up space if half the array is unused.
if (this.cursor_ > this.array_.length / 2) {
this.array_.splice(0, this.cursor_);
this.cursor_ = 0;
}
return x;
}
this.array_ = [];
this.cursor_ = 0;
}
Run Code Online (Sandbox Code Playgroud)
旁注:这里无关紧要,但为了记录,要将 70,000 个元素推送到您的数组中,您的循环应该从 0: 开始for (var i = 0; i < 70000; i++) {...}。正如所写,您只推送 69,999 个元素。
旁注 2:通过“parseInt”将双精度舍入为整数非常慢,因为它首先将双精度格式化为字符串,然后将该字符串读回为整数。更快的方法是Math.floor(Math.random() * 10000)). (为了这个测试的目的,你也可以简单地 push i。)
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |