Why does Array.prototype.fill () have such a big performance difference compared to the `for` loop?

When doing a little testing (Chrome on macOS) of the Array.prototype.fill() ) method, it is obviously almost twice as slow (if not slower) than just creating your own for loop and populating your array.

Obviously something like:

 for( var i = 0; i < Array.length; i++) { A[i] = 0; } 

vs

 Array.fill(0); 

The Array.fill() method will take ~ 210-250 ms to fill an array of size 10000000, while a for loop will take ~ 70-90 ms. It just seems that the Array.fill() method can be rewritten to just use a straight forward loop, since you always know your starting index and target index.

 let arrayTest = new Array(10000000), startTime, endTime; startTime = performance.now(); arrayTest.fill(0); endTime = performance.now(); console.log("%sms", endTime - startTime); arrayTest = new Array(10000000); startTime = performance.now(); for (let i = 0; i < arrayTest.length; i++){ arrayTest[i] = 0; } endTime = performance.now(); console.log("%sms", endTime - startTime); 

The above shows even greater discrepancy compared to when I tested locally.

Edit: Now I understand that after further testing, the discrepancies are significantly reduced when switching to Firefox and its engine-dependent. I guess this is mainly the result of how different JavaScript engines optimize loops against a method. It seems that the loop in Array.prototype.fill() can be optimized to eliminate this difference.

+5
source share
1 answer

The result is consistent with reports that parts of Chrome are written in JavaScript and rely on profiling and optimizing runtimes to improve performance.

I packed the test code into a function that will be called repeatedly from the test page, which can be loaded into different browsers (this is not an executable fragment):

 <!DOCTYPE html> <html><head><meta charset="utf-8"> <title>Array.prototype.fill</title> <script> Array.prototype.customFill = function( value, start = 0, end = this.length) { var count = end-start; if( count > 0 && count === Math.floor(count)){ while( count--) this[start++]=value; } return this; } function test() { let arrayTest, startTime, endTime, arraySize = 1000000; arrayTest = new Array(arraySize); startTime = performance.now(); for (let i = 0; i < arrayTest.length; i++){ arrayTest[i] = 0; } endTime = performance.now(); console.log("%sms (loop)", endTime - startTime); arrayTest = new Array(arraySize); startTime = performance.now(); arrayTest.fill(0); endTime = performance.now(); console.log("%sms (fill)", endTime - startTime); arrayTest = new Array(arraySize); startTime = performance.now(); arrayTest.customFill(0); endTime = performance.now(); console.log("%sms (custom fill)", endTime - startTime); } </script> </head> <body> open the console and click <button type="button" onclick="test()">test</button> </body> </html> 

The array size can be adjusted according to the performance of the device used.

The results for Chrome on Windows showed a big performance gain for the loop for the first two test clicks on the test. In a second click, the time for the cycle seemed to improve. On the third click, both cycle and fill methods were optimized and worked at almost equal and improved speed. The results were repeated after page reload.

I believe this is consistent with Chrome script optimization strategies and is incompatible with the fact that Chrome Array.prototype.fill written in C ++ or similar. Although Array.prototype.fill.toString() tells the function body as "native code," it does not say what language it is written in.


Update

Added timings for a custom fill method recorded for speed and saved as Array.prototype.customFill .

Timing for Firefox is consistent with Array.prototype.fill recorded in the script. The native implementation was superior to the loop and usually (but not always) faster than the custom fill method.

The timing for showing Chrome is also consistent with Array.prototype.fill , written in a script that becomes optimized. All three tested fill methods showed an increase in speed after one or two test clicks.

However, the custom padding method runs more than ten times faster than the original version of Chromes. You will need to enter meaningless code into the user method to slow it down enough to get closer to the initial speed of the original method. Conversely, after optimization, your own method is about two times faster - a custom method written in JavaScript is never optimized to the same extent.

While the Chromes Array.prototype.fill method can be written in JavaScript, an additional explanation is required to explain the initial slowness and the final performance optimization.

+1
source

Source: https://habr.com/ru/post/1275408/


All Articles