Google App Script – What Loop is Faster for Iterating Over an {Object}?

While on a Google Apps Script Discord Server a great question came up as to what loop was faster when iterating over an object. If you are curious about Array loops please see this post. After some poking around the net we found lots of answers but every answer was specific to their platform or to a certain browser. So I thought it might be nice to do some testing for Google App Scripts. I am not sure if Google App Script IDE is affected by your browser or machine speed at all but thought it would be fun to post the results of my test.

Forwards

BIG shout out to Rahul’s Blog that give some really good ways to test each loop. I based my my code on their code and the only difference is I am not using a library to measure time and I am just using a Date constructor to do my timing. I have asked permission to re-run his tests and come to my own conclusions for GAS. So credit given where credit due. Thanks Rahul!

Pre Thoughts

A Date constructor is only accurate to the millisecond so it is not super accurate. To adjust for this I decided to run more tests to help get more accuracy.

Google App Scripts execution times can swing wildly swings because of many different factors and Google. IE I have scripts that take 60 seconds to run one time and 180 seconds the next time. So by running more tests I hope to help average out these issues.

All tests are all preformed one at a time and I have tried to choose a number of loops so that all the test can run inside of the 6 minute limit that Google gives for a GAP. I did some testing first to see what the longest loop code was first and then tried to find the most amount of loops I could do inside of a 5 minute window to ensure all the test were the same and as accurate as possible (the longer they run the more accurate I am hoping the average will be).

Setup

I created a new Google App Script project and added the following code to it

function test() {
  var dictionary = {};
  for (var i = 0; i < 1000000; i++){
    dictionary[String(i)] = i ;
  }
  var d1 = new Date();
  for (var iterationNumber = 0 ; iterationNumber < 100; iterationNumber++){
   // Place test code here to test
  }
  var d2 = new Date();
  Logger.log(`On average it took ${(d2.getTime() - d1.getTime())/100} ms`);
}

Explanation of Code

The first loop is to create an array of 1 million elements (0 – 999,999).

Captures the date.

We then run through a loop 100 times and inside that loop we test our loop code.

Capture the date again.

We subtract the 2nd date in milliseconds from the 1st date in milliseconds to get how long it took in total and then divide that answer by the number of loops we did to get an average time in milliseconds.

The reason we go through the loop so many times to test the loop code is because most loops are so fast we don’t have an accurate way to measure the amount of time it takes to complete and have an accurate enough number to allow for comparison. By running the test more times and then averaging it we get a more accurate measurement that also takes into account slowdowns of the service.

Different Ways to Loop

for…in Statement

for (key in dictionary){
    dictionary[key];
}

Object.entries() Method

Object.entries(dictionary).forEach(
    pair => pair[1]
);

Object.values() Method

Object.values(dictionary).forEach(
    value => value
);

Object.keys() Method

Object.keys(dictionary).forEach(
    key => dictionary[key]
);

Object.getOwnPropteryNames() Method

Object.getOwnPropertyNames(dictionary).forEach(
    key => dictionary[key]
);

Results

Loop Type Milliseconds
1stObject.values() Method27.76
2ndfor…in Statement266.08
3rdObject.keys() Method299.72
4thObject.getOwnPropteryNames() Method474.45
5thObject.entries() Method789.91
100 Iterations

Conclusion

There is no need to do any more tests as there is a clear winner here. I had to retest as I did not believe the result because it was so far away form the others

There you have it, start using the Object.values() Method!

© MrCaspan 2021