sitelink4 http://1 
extra_vars4 ko 
extra_vars5 http://www.scottlogic.co.uk/2010/10/javascript-array-performance/ 
extra_vars6 sitelink1 

I was recently reading Google’s JavaScript Style Guide when I came across the following claim:

“Note that since assigning values to an array is faster than using push() you should use assignment where possible.”

I had always used push to assign a value to the end of an array, so thought I’d investigate this a little bit further to determine the performance of each of the methods. There are 3 distinct ways to do this:

  1. Array.push(element) ? Defined on the native Array object, this is the method challenged by Google.

  2. array[i] = element ? Assigning an element to a specific index of the array. The requirement of this method is that you must have a pointer to the last location. Other than that it’s a simple assignment.

  3. array[array.length] = element ? Similar to the previous, but this involves a lookup for situations where you don’t have access to a pointer.

  4. I also defined a fourth function to test. I put a function on the Array prototype called mypush, which carried out step 3 above. It was defined as such:

      Array.prototype.mypush = function(element) {
        this[this.length] = element;
      };

This short article will document my testing of these different methods on several browsers.

The Tests

I put together a small HTML page to execute the different methods of adding an element to the end of an array alongside some method of timing how long each took.

The tests consisted of adding 400,000 elements to an empty Array using the different methods described above. I performed the test 10 times for each method, and took the average. For example, here’s a look at the test for Array.push:

  function testPush() {
    var result = 0;
    var a = [];
 
    for (var i = 0; i<10; i++) { // run the test 10 times
      a = []; // we start with an empty array each time
      var start = new Date().getTime(); // get the start time of the test
 
      for (var j = 0; j<400000; j++) {
        a.push(i);
      }
 
      var end = new Date().getTime();
      result += end - start;  // and the result is the end time minus the start time
    }
 
    alert('Result for Array.push is ' + (result / 10)); // take the average
  }

I then repeated the same logic for the other methods.

The Results

The tests yielded the following results in the following browsers:

Google Chrome 6.0.472.63Mozilla Firefox 3.6.10Apple Safari 5.0 (7533.16)Internet Explorer 8Internet Explorer 7Opera 10.62
Array.push0.4 ms5 ms2 ms21.7 ms66.7 ms2.7 ms
array[i]1 ms0.8 ms0.9 ms4.6 ms29.4 ms0.7 ms
array[array.length]1.2 ms0.9 ms0.9 ms10.9 ms32.6 ms1 ms
Array.mypush1.2 ms7.1 ms1.2 ms31 ms86.8 ms1.2 ms

Conclusion

The results speak for themselves: using an index outperforms using Push in every browser with the exception of Google’s own. If cross-compatibility is a big concern for you, the utilitarian approach would be to use an index wherever possible.

To look at the situation a little deeper, we could consider steps the Closure Compiler takes to handle these situations. If we run the following code in the Compiler:

var a = [];
 
function push(i) {
  a.push(i);
}
 
for(var i = 0; i<10; i++) {
  a.push(i);
}

We observe the following output:

  for(var a=[],b=0;b<10;b++)a.push(b);

Showing that the Compiler doesn’t do anything about push statements in pre-compiled code. However, with an improved performance in most browsers, you might expect it to.

However, it wouldn’t be as simple as converting all pushes to index assignments as there is a subtle difference between the two; Array.push returns the length of the array after the element has been added (something you don’t get with array[array.length]). Converting all Array.push statements would cause semantic problems if the user has assigned that statement to a variable. For example:

var a = [];
var b = [];
 
var i = a.push('test'); // i is 1
 
var j = b[b.length] = 'test'; // j is 'test'

However, we could examine the case where the result of Array.push is not assigned to anything. In this scenario, the Compiler should be able to replace the push with an array.length index without side effects.

The problem then lies in the fact that the performance varies between browser. Although, on the whole, indexing performs better than push, that is not the case in Google Chrome. Unlike GWT, where you can deploy a certain condition for a certain browser, Closure Compiler just generates one JavaScript file for every browser.

Given the differences between Chrome’s results, and the extremely poor performance in some other browsers, it may be worth sacrificing some performance in Chrome for much better performance in other browsers.


This entry was posted on Friday, October 15th, 2010 and is filed under Blog.

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site .


6 Responses to “JavaScript Array.push Performance”

    • Yes. Despite Google’s advice, the Array insert function they have defined in the Closure Library still uses Array.push [source].

      Like you said, I’m not sure that increasing an array by a constant value on each push makes sense in JavaScript, mainly because it’s not consistent with the language specification. The following example could cause some confusion and is generally inconsistent with JavaScript arrays:

        var a = [];
        a.myPush(1) // this code has no side effects if you don't assign it back to a. a hasn't changed
        a = a.myPush(1) // length is now 11, but the array is [1]

      You now have to introduce a size property to keep track of how many elements are in the Array, which doesn’t fit the specification.

      To answer your question about improving new Array().. I would stick to using array literals. You wouldn’t need to use the Array constructor as it’s generally considered to be more bloated than the literal notation (the extra overhead incurred with finding the constructor etc.). You could just increase the length of arrayToReturn by 10.

        var a = [];
        a.length = a.length + 10;
        // a.length = 10
       
        a = [];
        a = a.concat(new Array(10));
        // a.length = 10
번호 제목 글쓴이 날짜 조회 수
246 [Gemini] ajax 와 fetch 의 차이 황제낙엽 2025.01.04 3419
245 [검토 완료] 디바이스 카메라로 촬영한 사진을 서버에 업로드하기 샘플 황제낙엽 2024.11.21 3987
244 브라우저에서 이미지를 편집(crop 등) 할 수 있는 오픈소스 Cropper.js 황제낙엽 2024.11.16 3842
243 [ChatGPT] json data 의 정렬 [1] 황제낙엽 2024.07.23 3352
242 DOMContentLoaded 이벤트와 window.onload 이벤트 황제낙엽 2024.07.15 3669
241 fetch() 사용 예제들 황제낙엽 2024.07.09 3380
240 [Copilot] Vanilla JavaScript에서 외부 스크립트 파일에 정의된 함수들을 로드 황제낙엽 2024.06.21 3758
239 [Copilot] ES6 모듈(module) 문법 황제낙엽 2024.06.21 3805
238 [Copilot] JSON 객체 내부 데이터를 순회하면서 조회하는 코드 황제낙엽 2024.06.02 3270
237 [Copilot] JavaScript로 서버에 특정 값을 POST 방식으로 전달하고 응답을 기다리지 않고 바로 종료 황제낙엽 2024.05.31 3615
236 json 데이터 내의 변수명에 prefix 로 type 표현하기 황제낙엽 2024.04.15 3361
235 fetch() 함수 사용 예제 file 황제낙엽 2023.11.23 3605
234 현재 document 의 host 와 port 를 얻는 방법 황제낙엽 2023.10.03 4209
233 (Bard) FileReader 로 여러개의 파일을 read 하는 법 file 황제낙엽 2023.08.23 3660
232 How to build a file upload service with vanilla JavaScript file 황제낙엽 2023.08.22 3715
231 (Bard) JavaScript로 JSON 배열을 작성하는 방법 황제낙엽 2023.08.21 3672
230 모바일 브라우저에서 file input element 를 이용하여 여러장의 이미지를 서버에 전송하려 할때 [1] 황제낙엽 2023.08.21 3703
229 navigator.mediaDevices 황제낙엽 2023.08.21 3798
228 Barcode Detection API 황제낙엽 2023.08.06 3854
227 정규식을 이용한 이메일 검증 스크립트 file 황제낙엽 2023.06.25 2894