Google App Script – What Loop is Faster for Iterating Over an [Array]?

While on a Google Apps Script Discord Server a great question came up as to what loop was faster when iterating over an array. If you are curious about Object 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 numbers = []
  for (var i = 0; i < 1000000; i++){
      numbers.push(i)
  }
  var d1 = new Date();
  for (var iterationNumber = 0 ; iterationNumber < 1000; iterationNumber++){
   // Place test code here to test
  }
  var d2 = new Date();
  Logger.log(`On average it took ${(d2.getTime() - d1.getTime())/1000}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 x1000 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

Map() Method

numbers.map( num => num );

forEach() Method

numbers.forEach( num => num );

For…in Statement

for (num in numbers) { 
    num;
}

For…of Statement

for (num of numbers) { 
    num;
}

For Loop – Count Up

for (var num = 0; num < numbers.length; num++) { 
    numbers[num];
}

For Loop – Count Down

for (var num = numbers.length; num >= 0 ; num--) { 
    numbers[num];
}

For Loop – Count Up (length referenced)

const length = numbers.length;
for (var num = 0; num < length ; num++) { 
    numbers[num];
}

For Loop – Count Down (length referenced)

const length = numbers.length;
for (var num = length; num >= 0 ; num--) { 
    numbers[num];
}

While Loop – Count Up

var num = 0;
while (num < numbers.length) { 
    numbers[num];
    num+=1;
}

While Loop – Count Down

var num = numbers.length;
while (num > 0) { 
    numbers[num];
    num-=1;
}

While Loop – Count Up (length referenced)

const length = numbers.length;
var num = 0;
while (num < length) { 
    numbers[num];
    num+=1;
}

Results

Loop Type Milliseconds
1stfor Loop – Count Up (length referenced)0.575
2ndwhile Loop – Count Up (length referenced) 0.639
3rdfor Loop – Count Up0.664
4thfor Loop – Count Down0.748
5thfor Loop – Count Down (length referenced) 0.846
6thwhile Loop – Count Up0.877
7thwhile Loop – Count Down1.427
8thfor…of Statement2.107
9thforEach Method23.537
10thMap Method39.050
11thFor…in Statement287.585
1000 iterations

Now that we know which ones by far are the slowest I am going to remove them so that we can test the fastest ones only to see if we get the same results. Let’s remove anything that is above 1 ms and really hammer these chunks of code by looping over them 350,000 times

Loop TypeMilliseconds
1stwhile Loop – Count Up (length referenced)0.564
2ndfor Loop – Count Up (length referenced)0.642
3rdwhile Loop – Count Up0.629
4thfor Loop – Count Up0.666
5thfor Loop – Count Down0.845
6thfor Loop – Count Down (length referenced) 1.035
350,000 iterations

So looking at this we can infer a few things maybe more iterations are subject to more delays or server slow downs maybe this is a more accurate number. Who knows. A few changed place but relatively stayed the same. For giggles I decided to just do 10 loops as most people would not be hammering a loop this bad and it’s not realistic

Loop TypeRun 1Run 2Run 3
for Loop – Count Up (length referenced)1.31.41.5
while Loop – Count Up (length referenced) 1.21.61.5
for Loop – Count Up1.61.41.8
for Loop – Count Down1.22.01.8
for Loop – Count Down (length referenced) 1.52.02.1
while Loop – Count Up2.01.43.3
while Loop – Count Down2.12.62.2
for…of Statement13.611.69.9
forEach Method19.221.218.6
Map Method36.141.930.3
For…in Statement276.8343.5296.3
10 iterations

Conclusion

Take it for what it is, just a bunch of silly tests but they still show some results that we can be assured of:

  1. a ‘for…in’ statement is horribly slow in GAS, don’t use them!
  2. A ‘for Loop’ seems to be the most efficient way in GAS to iterate over an array

Take my results as you will, Peace Out!

© MrCaspan 2021