简体   繁体   中英

Object key vs array lookup performance

Example 1:

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

Example 2:

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

I'm storing members in an array on each piece of content like in Example 1, but doing it like this I'd have to iterate through 49999 items in my the array, to find member 50000, so I was thinking simply checking if a specific key is defined within the javascript object would be a better approach here, although I do not need to store a value, but only check whether the key is undefined or not?

What I need is to be able to check if eg. "member50000" exists as a value within my array - or as a key inside my object.

I did some benchmarking tests, but I'm not sure I've come to the right conclusion, or if I'm doing something wrong in my comparison: http://jsperf.com/lolda123

According to the above test results, would it then be fair to conclude that saving a key/value pair within an object where the value is boolean (true), and doing if(obj["member50000"]) is the best performing option? Even if no property with the given key even exists? As I see it, according to my test results, checking for the existence of the key itself, would seem much more expensive in terms of performance, but checking if the key is there, really is all I need.

I don't care about the value, so am I missing something here, or why would the better solution seem like being the one where you look up the value, by the key, instead of just looking up the key, inside the object?

Well I thought the same thing, that using an Object will be faster, and I proved myself wrong!

I ran the performance tests using the same stack as jsPerf on NodeJS 6.3 ( V8 engine ):

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

The results are:

  • lookup is much faster on larger data sets
  • creating the Object datastructure ( basically a HashMap ) is EXPENSIVE! and much slower than using an array
  • when combined insert and lookup, array.indexOf is faster by a very big margin

If you believe I made a mistake in any of my tests feel free to bring it up and we can retest. Though so far looks like array.indexOf is much faster.

obj.hasOwnProperty is much faster than arr.indexOf http://jsperf.com/array-hasownproperty-vs-array-indexof

Using arr.indexOf should also be faster than any looping you do.

Was curious about this since Object.prototype is an ancestor of any array instance, therefore it must be bulkier than an object and slower when it comes to property lookup.

In my test I store a list of strings as array elements and an object keys. Then I measure how much time it takes to check for existance of each key in both object and array implementations. Repeat 100000 times.

Generally, objects happen to be faster. Null objects are significantly faster on 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).`);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM