Array VS. Object Efficiency in JavaScript

Array vs. Object efficiency in JavaScript

The short version: Arrays are mostly faster than objects. But there is no 100% correct solution.

Update 2017 - Test and Results

var a1 = [{id: 29938, name: 'name1'}, {id: 32994, name: 'name1'}];

var a2 = [];
a2[29938] = {id: 29938, name: 'name1'};
a2[32994] = {id: 32994, name: 'name1'};

var o = {};
o['29938'] = {id: 29938, name: 'name1'};
o['32994'] = {id: 32994, name: 'name1'};

for (var f = 0; f < 2000; f++) {
var newNo = Math.floor(Math.random()*60000+10000);
if (!o[newNo.toString()]) o[newNo.toString()] = {id: newNo, name: 'test'};
if (!a2[newNo]) a2[newNo] = {id: newNo, name: 'test' };
a1.push({id: newNo, name: 'test'});
}

test setup
test results

Original Post - Explanation

There are some misconceptions in your question.

There are no associative arrays in Javascript. Only Arrays and Objects.

These are arrays:

var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";

This is an array, too:

var a3 = [];
a3[29938] = "a";
a3[32994] = "b";

It's basically an array with holes in it, because every array does have continous indexing. It's slower than arrays without holes. But iterating manually through the array is even slower (mostly).

This is an object:

var a3 = {};
a3[29938] = "a";
a3[32994] = "b";

Here is a performance test of three possibilities:

Lookup Array vs Holey Array vs Object Performance Test

An excellent read about these topics at Smashing Magazine: Writing fast memory efficient JavaScript

JavaScript object vs. array lookup performance

The answer to this is browser dependent, however, there are a few performance tests on jsperf.com on this matter. It also comes down to the size of your data. Generally it is faster to use object key value pairs when you have large amounts of data. For small datasets, arrays can be faster.

Array search will have different performance dependent on where in the array your target item exist. Object search will have a more consistent search performance as keys doesn't have a specific order.

Also looping through arrays are faster than looping through keys, so if you plan on doing operations on all items, it can be wise to put them in an array. In some of my project I do both, since I need to do bulk operations and fast lookup from identifiers.

A test:

http://jsben.ch/#/Y9jDP

Javascript Set vs. Array performance

Ok, I have tested adding, iterating and removing elements from both an array and a set. I ran a "small" test, using 10 000 elements and a "big" test, using 100 000 elements. Here are the results.

Adding elements to a collection

It would seem that the .push array method is about 4 times faster than the .add set method, no matter the number of elements being added.

Iterating over and modifying elements in a collection

For this part of the test I used a for loop to iterate over the array and a for of loop to iterate over the set. Again, iterating over the array was faster. This time it would seem that it is exponentially so as it took twice as long during the "small" tests and almost four times longer during the "big" tests.

Removing elements from a collection

Now this is where it gets interesting. I used a combination of a for loop and .splice to remove some elements from the array and I used for of and .delete to remove some elements from the set. For the "small" tests, it was about three times faster to remove items from the set (2.6 ms vs 7.1 ms) but things changed drastically for the "big" test where it took 1955.1 ms to remove items from the array while it only took 83.6 ms to remove them from the set, 23 times faster.

Conclusions

At 10k elements, both tests ran comparable times (array: 16.6 ms, set: 20.7 ms) but when dealing with 100k elements, the set was the clear winner (array: 1974.8 ms, set: 83.6 ms) but only because of the removing operation. Otherwise the array was faster. I couldn't say exactly why that is.

I played around with some hybrid scenarios where an array was created and populated and then converted into a set where some elements would be removed, the set would then be reconverted into an array. Although doing this will give much better performance than removing elements in the array, the additional processing time needed to transfer to and from a set outweighs the gains of populating an array instead of a set. In the end, it is faster to only deal with a set. Still, it is an interesting idea, that if one chooses to use an array as a data collection for some big data that doesn't have duplicates, it could be advantageous performance wise, if there is ever a need to remove many elements in one operation, to convert the array to a set, perform the removal operation, and convert the set back to an array.

Array code:

var timer = function(name) {  var start = new Date();  return {    stop: function() {      var end = new Date();      var time = end.getTime() - start.getTime();      console.log('Timer:', name, 'finished in', time, 'ms');    }  }};
var getRandom = function(min, max) { return Math.random() * (max - min) + min;};
var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];
var genLastName = function() { var index = Math.round(getRandom(0, lastNames.length - 1)); return lastNames[index];};
var sex = ["Male", "Female"];
var genSex = function() { var index = Math.round(getRandom(0, sex.length - 1)); return sex[index];};
var Person = function() { this.name = genLastName(); this.age = Math.round(getRandom(0, 100)) this.sex = "Male"};
var genPersons = function() { for (var i = 0; i < 100000; i++) personArray.push(new Person());};
var changeSex = function() { for (var i = 0; i < personArray.length; i++) { personArray[i].sex = genSex(); }};
var deleteMale = function() { for (var i = 0; i < personArray.length; i++) { if (personArray[i].sex === "Male") { personArray.splice(i, 1) i-- } }};
var t = timer("Array");
var personArray = [];
genPersons();
changeSex();
deleteMale();
t.stop();
console.log("Done! There are " + personArray.length + " persons.")

Javascript efficiency: big object vs many arrays

Which way is better? Well, we are talking about basic OOP, here: you have many different "arrays" which contains information about a client, and the information of a client is scattered through many different arrays, and every array must share the index with another 10 arrays.

You have a problem: what happens when you remove a socket from the sockets array, but do not remove the position? BUG!

So, if a client is a client, treat it as a whole, with 10 (in your example) composite properties, about the client's socket, his attributes, etc.

Please, don't think about "efficiency". Your question's answer is not about efficiency, is about maintainability, robustness and simplicity. This things usually drive you naturally toward better performance, but you should care about performance only if you have a performance problem.

Remember (write it down on a wall): Premature optimization is the root of all evil.

Performance of array includes vs mapping to an Object and accessing it in JavaScript

It's true that object lookup occurs in constant time - O(1) - so using object properties instead of an array is one option, but if you're just trying to check whether a value is included in a collection, it would be more appropriate to use a Set, which is a (generally unordered) collection of values, which can also be looked up in linear time. (Using a plain object instead would require you to have values in addition to your keys, which you don't care about - so, use a Set instead.)

const set = new Set(['foo', 'bar']);
console.log(set.has('foo'));
console.log(set.has('baz'));


Related Topics



Leave a reply



Submit