gpt4 book ai didi

Javascript 对象与映射/设置键查找性能

转载 作者:行者123 更新时间:2023-12-04 13:09:35 26 4
gpt4 key购买 nike

我试图探索javascript ObjectMap 相比执行或 Set用于正常的 key 访问。
所以我在 JSBEN.CH 上运行了以下 3 个代码(这里是测试链接:https://jsben.ch/q4RPK)
对象

  const object = {};

for (let i = 0; i < 10000; ++i) {
object[`key_${i}`] = 1;
}

let result = 0;

for (let i = 0; i < 10000; ++i) {
result += object[`key_${i}`];
}
map
  const map = new Map();

for (let i = 0; i < 10000; ++i) {
map.set(`key_${i}`, 1);
}

let result = 0;

for (let i = 0; i < 10000; ++i) {
result += map.get(`key_${i}`);
}
套装
  const set = new Set();

for (let i = 0; i < 10000; ++i) {
set.add(`key_${i}`);
}

let result = 0;

for (let i = 0; i < 10000; ++i) {
result += set.has(`key_${i}`);
}
正如您可以查看测试链接, mapset然而似乎表现几乎相似 objects每次都慢得多。谁能解释一下 objects 的原因是什么?表现比 map 差或 set用于基本的 key 访问操作?
编辑 1 : 事实证明,只需在 objects 上设置键也比 map/set 慢: https://jsben.ch/al9ef

最佳答案

只看相对数字总是很危险的,这里有一些绝对数字,在 Intel 8350U 上的 NodeJS v14.14.0 上运行:


迭代
对象写入
对象读取
map 写入
map 读取


100
0ms
0ms
0ms
0ms

1.000
3ms
1ms
0ms
0ms

10,000
7ms
4毫秒
8ms
1ms

1.000.000
1222毫秒
527毫秒
632毫秒
542毫秒


可以看到,对于 10.000 次迭代,在上面的运行中对象和 map 之间的差异是 1 毫秒,因为这是时间测量的准确性,我们无法从该测试中真正得出任何结论。结果是绝对随机的。
对于 100 万次迭代,我们可以看到 Map 写入优于 Object 写入的明显优势,读取性能非常相似。现在,如果我们看绝对数字,这仍然是 100 万次写入/秒。因此,尽管对象写入要慢得多,但这不太可能成为您的应用程序的瓶颈。
为了获得准确的解释,必须分析引擎执行的所有步骤。为此,您可以运行 node --print-code并分析运行的字节码。我没有时间这样做,尽管这里有一些观察:

  • 如果对象是用 Object.create(null) 构造的(没有原型(prototype))性能大致相同,因此原型(prototype)查找根本不会影响性能。
  • 第 20 次迭代后,V8 选择内部表示 dictionary_map对于 object ,所以这基本上是一个哈希映射与另一个哈希映射竞争(可以运行 node --allow-natives-syntax 然后使用 %DebugPrint(object) 来获得内部表示)。

  • 作为引用,这里是用于运行基准测试的代码:

    function benchmark(TIMES) {  
    console.log("BENCHMARK ", TIMES);

    const object = Object.create(null);

    let start = Date.now();
    for (let i = 0; i < TIMES; ++i) {
    object[`key_${i}`] = 1;
    }

    console.log("Object write took", Date.now() - start);
    start = Date.now();

    let result = 0;

    for (let i = 0; i < TIMES; ++i) {
    result += object[`key_${i}`];
    }

    console.log("Object read took", Date.now() - start);
    start = Date.now();




    const map = new Map();

    for (let i = 0; i < TIMES; ++i) {
    map.set(`key_${i}`, 1);
    }

    console.log("Map write took", Date.now() - start);
    start = Date.now();

    result = 0;

    for (let i = 0; i < TIMES; ++i) {
    result += map.get(`key_${i}`);
    }

    console.log("Map read took", Date.now() - start);

    }

    benchmark(100);
    benchmark(1_000);
    benchmark(10_000);
    benchmark(1_000_000);

    总结一下:
  • 将 Maps 用于具有许多不同的、不断变化的键的字典,因为它们比内部表示为哈希表的对象略好
  • 使用对象 - 好 - 对象。如果您的键数量较少并且经常访问它们,对象会更快(因为引擎可以使用内联缓存、具有固定内存布局的隐藏类等)
  • 关于Javascript 对象与映射/设置键查找性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66931535/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com