node.js - 为什么 nodejs 数组移位/推送循环在数组长度 87369 以上运行速度慢 1000 倍?

标签 node.js performance v8

为什么 nodejs 数组移位/压入操作的速度与数组大小不是线性关系? 87370 处有一个戏剧性的拐点,完全压垮了系统。

试试这个,首先在 q 中使用 87369 个元素,然后使用 87370。(或者,在 64 位系统上,尝试 85983 和 85984。)对我来说,前者运行时间为 0.05 秒;后者在 80 秒内——慢了 1600 倍。 (在 Node v0.10.29 的 32 位 debian linux 上观察到)

q = [];

// preload the queue with some data
for (i=0; i<87369; i++) q.push({});

// fetch oldest waiting item and push new item
for (i=0; i<100000; i++) {
    q.shift();
    q.push({});
    if (i%10000 === 0) process.stdout.write(".");
}

64 位 debian linux v0.10.29 从 85984 开始抓取并在 .06/56 秒内运行。 Node v0.11.13 具有类似的断点,但数组大小不同。

最佳答案

Shift 对数组来说是一个非常慢的操作,因为您需要移动所有元素,但是当数组内容适合页面 (1mb) 时,V8 能够使用一个技巧来快速执行它。

空数组以 4 个槽开始,当您不断插入时,它将使用公式 1.5 * (old length + 1) + 16 调整数组的大小。

var j = 4;
while (j < 87369) {
    j = (j + 1) + Math.floor(j / 2) + 16
    console.log(j);
}

打印:

23
51
93
156
251
393
606
926
1406
2126
3206
4826
7256
10901
16368
24569
36870
55322
83000
124517 

所以你的数组大小最终实际上是 124517 个项目,这使得它太大了。

您实际上可以将您的数组预分配到正确的大小,它应该能够再次快速移动:

var q = new Array(87369); // Fits in a page so fast shift is possible

// preload the queue with some data
for (i=0; i<87369; i++) q[i] = {};

如果你需要更大的,使用 the right data structure

关于node.js - 为什么 nodejs 数组移位/推送循环在数组长度 87369 以上运行速度慢 1000 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27341352/

相关文章:

node.js - Node 将 Promise 与异步模块结合使用

node.js - 如何在 multer 中捕获错误

node.js websocket 模块已安装但在脚本中不起作用

json - 使用终端在特定目录中创建 json 文件

objective-c - 私有(private)成员是否增加任何性能优势?

javascript - 如何确定 Firefox 在应用程序空闲时燃烧 CPU "Recalculating Style"的原因?

linux - 为什么将文件系统类型从 XFS 更改为 JFS 会提高 mmap 文件写入性能?

c++ - 从 V8 中的 C++ 回调调用 Javascript 函数

c++ - 从嵌入式 v8 调用 WebAssembly,无需 JS

javascript - Android Javascript 引擎;需要用Rhino、J2V8等替换WebView