对象键vs数组查找性能

Object key vs array lookup performance

本文关键字:查找 性能 数组 vs 对象      更新时间:2023-09-26

示例1:

["member1", "member2",...,..., "member100000"]

示例2:

{
    "member1": true, // (doesn't really need values, only keys :/)
    "member2": true,
    "...",
    "member100000": true
}

我将成员存储在数组中,就像在示例1中一样,但是这样做,我必须在我的数组中迭代49999个项目,找到成员50000,所以我想简单地检查是否在javascript对象中定义了一个特定的键,这将是一个更好的方法,虽然我不需要存储一个值,但只检查键是否未定义?

我需要的是能够检查是否。"member50000"作为值存在于我的数组中,或者作为键存在于我的对象中。

我做了一些基准测试,但我不确定我是否得出了正确的结论,或者我在比较中是否做错了什么:http://jsperf.com/lolda123

根据上面的测试结果,是否可以公平地得出这样的结论:在一个值为布尔值(true)的对象中保存一个键/值对,并且执行if(obj["member50000"])是性能最好的选项?即使不存在具有给定键的属性?正如我所看到的,根据我的测试结果,检查键本身是否存在,在性能方面似乎要昂贵得多,但检查键是否存在,确实是我所需要的。

我不关心值,所以我在这里遗漏了什么,或者为什么更好的解决方案似乎是通过键来查找值,而不是在对象内部查找键?

我也这么认为,使用Object会更快,但事实证明我错了!

我在NodeJS 6.3 (V8引擎)上使用与jsPerf相同的堆栈运行性能测试:

https://github.com/amoldavsky/js-array-indexof-vs-hashmap

结果如下:

  • 查找更大的数据集
  • 创建对象数据结构(基本上是HashMap)是昂贵的!并且比使用数组
  • 要慢得多
  • 当组合插入和查找时,数组。indexOf要快得多

如果你认为我在任何测试中犯了错误,请随时提出,我们可以重新测试。虽然到目前为止看起来像数组。

obj.hasOwnPropertyarr.indexOf快得多http://jsperf.com/array-hasownproperty-vs-array-indexof

使用arr.indexOf也应该比你做的任何循环都快。

我对此很好奇,因为Object.prototype是任何数组实例的祖先,因此它一定比对象更笨重,并且在查找属性时速度更慢。

在我的测试中,我将字符串列表存储为数组元素和对象键。然后测量在对象和数组实现中检查每个键是否存在所花费的时间。重复10万次

一般来说,对象碰巧更快。Null对象在chromium上明显更快。

{
  const iterations = 1000000;
  let arrTotal = 0;
  let objTotal = 0;
  let nullObjTotal = 0;
  let a = '';
  let keys = [
    "The standard Lorem Ipsum passage",
    "used since the 1500sLorem ipsum dolor sit amet",
    "consectetur adipiscing elit",
    "Ut enim ad minim veniam",
    "Excepteur sint occaecat cupidatat non proident",
    "sunt in culpa qui officia deserunt mollit anim id est laborum",
    "Section 1",
    "32 of de Finibus Bonorum et Malorum",
    "totam rem aperiam",
    "Neque porro quisquam est",
    "qui dolorem ipsum quia dolor sit amet",
    "consectetur",
    "adipisci velit",
    "Ut enim ad minima veniam",
    "the master-builder of human happiness",
    "No one rejects",
    "dislikes",
    "or avoids pleasure itself",
    "because it is pleasure",
    "because it is pain",
    "To take a trivial example",
    "which of us ever undertakes laborious physical exercise",
    "33 of de Finibus Bonorum et Malorum",
    "similique sunt in culpa qui officia deserunt mollitia animi",
    "id est laborum et dolorum fuga",
    "Et harum quidem rerum facilis est et expedita distinctio",
    "Nam libero tempore",
    "omnis voluptas assumenda est",
    "omnis dolor repellendus",
    "Itaque earum rerum hic tenetur a sapiente delectus",
    "1914 translation by H",
    "RackhamOn the other hand",
    "so blinded by desire",
    "These cases are perfectly simple and easy to distinguish",
    "In a free hour",
    "every pleasure is to be welcomed and every pain avoided",
    "or else he endures pains to avoid worse pains"
  ];
  let nullObj = Object.create(null);
  for (let key of keys) nullObj[key] = null;
  let obj = {
    "The standard Lorem Ipsum passage": null,
    "used since the 1500sLorem ipsum dolor sit amet": null,
    "consectetur adipiscing elit": null,
    "Ut enim ad minim veniam": null,
    "Excepteur sint occaecat cupidatat non proident": null,
    "sunt in culpa qui officia deserunt mollit anim id est laborum": null,
    "Section 1": null,
    "32 of de Finibus Bonorum et Malorum": null,
    "totam rem aperiam": null,
    "Neque porro quisquam est": null,
    "qui dolorem ipsum quia dolor sit amet": null,
    "consectetur": null,
    "adipisci velit": null,
    "Ut enim ad minima veniam": null,
    "the master-builder of human happiness": null,
    "No one rejects": null,
    "dislikes": null,
    "or avoids pleasure itself": null,
    "because it is pleasure": null,
    "because it is pain": null,
    "To take a trivial example": null,
    "which of us ever undertakes laborious physical exercise": null,
    "33 of de Finibus Bonorum et Malorum": null,
    "similique sunt in culpa qui officia deserunt mollitia animi": null,
    "id est laborum et dolorum fuga": null,
    "Et harum quidem rerum facilis est et expedita distinctio": null,
    "Nam libero tempore": null,
    "omnis voluptas assumenda est": null,
    "omnis dolor repellendus": null,
    "Itaque earum rerum hic tenetur a sapiente delectus": null,
    "1914 translation by H": null,
    "RackhamOn the other hand": null,
    "so blinded by desire": null,
    "These cases are perfectly simple and easy to distinguish": null,
    "In a free hour": null,
    "every pleasure is to be welcomed and every pain avoided": null,
    "or else he endures pains to avoid worse pains": null
  };
  let arr = [
    "The standard Lorem Ipsum passage",
    "used since the 1500sLorem ipsum dolor sit amet",
    "consectetur adipiscing elit",
    "Ut enim ad minim veniam",
    "Excepteur sint occaecat cupidatat non proident",
    "sunt in culpa qui officia deserunt mollit anim id est laborum",
    "Section 1",
    "32 of de Finibus Bonorum et Malorum",
    "totam rem aperiam",
    "Neque porro quisquam est",
    "qui dolorem ipsum quia dolor sit amet",
    "consectetur",
    "adipisci velit",
    "Ut enim ad minima veniam",
    "the master-builder of human happiness",
    "No one rejects",
    "dislikes",
    "or avoids pleasure itself",
    "because it is pleasure",
    "because it is pain",
    "To take a trivial example",
    "which of us ever undertakes laborious physical exercise",
    "33 of de Finibus Bonorum et Malorum",
    "similique sunt in culpa qui officia deserunt mollitia animi",
    "id est laborum et dolorum fuga",
    "Et harum quidem rerum facilis est et expedita distinctio",
    "Nam libero tempore",
    "omnis voluptas assumenda est",
    "omnis dolor repellendus",
    "Itaque earum rerum hic tenetur a sapiente delectus",
    "1914 translation by H",
    "RackhamOn the other hand",
    "so blinded by desire",
    "These cases are perfectly simple and easy to distinguish",
    "In a free hour",
    "every pleasure is to be welcomed and every pain avoided",
    "or else he endures pains to avoid worse pains"
  ];
  for (let i = 0, stamp = 0, length = keys.length; i < iterations; ++i) {
    stamp = performance.now();
    for (let j = 0; j < length; ++j) {
      if (keys[j] in obj) a = keys[j];
    }
    objTotal += (performance.now() - stamp)/1000;
    stamp = performance.now();
    for (let j = 0; j < length; ++j) {
      if (~arr.indexOf(keys[j])) a = keys[j];
    }
    arrTotal += (performance.now() - stamp)/1000;
    stamp = performance.now();
    for (let j = 0; j < length; ++j) {
      if (keys[j] in nullObj) a = keys[j];
    }
    nullObjTotal += (performance.now() - stamp)/1000;
  }
  console.log(`Array total: ${arrTotal}; Array avarage: ${arrTotal/iterations}(s).`);
  console.log(`Object total: ${objTotal}; Object avarage: ${objTotal/iterations}(s).`);
  console.log(`Null object total: ${nullObjTotal}; Null object avarage: ${nullObjTotal/iterations}(s).`);
}