Javascript array (push vs initialize with size) 성능 비교 (부제: 자바스크립트의 배열은 우리가 알던 배열이 아니다)

Falcon·2021년 4월 1일
2

javascript

목록 보기
2/28

🎯 목적

제목에서 어그로 끌었다.
성능 또 성능, 100만번 이상의 loop을 돌면서 몇 ms 단위로라도 실행시간을 단축시키고자 하는 사람들을 위해 javascript array 의 속내를 들여다보자.

이 글에서 알고자하는 것은 한줄요약하면

"(1) 빈 배열을 생성하고 원소를 그냥 우겨넣는 방식과 (2) 사이즈를 지정하여 초기화하고 값을 할당하는 방식에 속도차이가 있나?" 를 확인하는 것이다.

사용법

(1) 원소 추가
Array.prototype.push() 메소드를 사용하면된다.
✒️ tip) 자바스크립트는 기본적으로 타입이 없기 때문에 한 배열에 서로 다른 타입의 원소를 넣어도 문제가 되지 않는다.
(물론 타입스크립트로 명시적으로 자료형을 선언하면 트랜스파일링시 에러를 반환한다. 혹은 그 이전에 IDE 창에서)

(2) 배열 사이즈 명시적 초기화
new Array(array_length)

성능 비교 테스트 1 (node.js)

1. push

빈 배열을 선언하고, 랜덤숫자를 스트링으로 변환하여 200억회 추가한다.

console.time("test");

function test() {
    const strArray : string[] = [];
    for (let i : number = 1; i <= 2_000_000_000; i++) {
        strArray.push(Math.random().toString());
    }
    strArray.forEach(console.log);
}

console.timeEnd("test");
// 0.063ms

2. assign

배열 크기를 200억으로 미리 지정하고 1번째 index 부터 넣어보자.

console.time("test2");

function test2() {
    const strArray : string[] = new Array(2_000_000_000);
    for (let i : number = 1; i <= 2_000_000_000; i++) {
        strArray[i] = Math.random().toString();
    }
    strArray.forEach(console.log)
}
console.timeEnd("test2");
// 0.062ms

이상한점을 눈치 챘나?
사실 사이즈가 200억이면 200억번째 인덱스는 존재하지 않는다.
근데 오류가나지 않는다.

js에서 배열은 같은 자료형을 미리 메모리에 잡아두는 것이 아닌
⭐ 배열이란 가면을 쓴 Hashmap 원소를 (key : index, value: value) 로 추가했을 뿐이기 때문이다.

0.001ms 밖에 차이나지 않는다. (200억 개 연산인데 이정도면 차이가 없다고 봐도 무방하다.)


성능 비교 테스트 2 (Chrome)

node.js 가 아닌 web browser 에서도 테스트해봤다.

차이가 없다. 이번엔 심지어 push()가 더 빨랐다.


📝 결론

일반적인 컴파일 언어 (C++의 vector.emplace_back() || push_back() , Java와 Kotlin의 ArrayList.add() )의 경우, 원소 추가 횟수가 많아져서 지정된 capacity를 넘어가면 O(N) 만큼의 복사가 일어나는 매커니즘을 가지고있어 속도가 느렸다.
따라서 배열의 크기를 미리 알 수 있다면 명시적으로 Capacity 를 지정해주는 방식의 초기화가 더 효율적이었다.

하지만 자바스크립트는 Capacity 를 지정하고 assign 한 방식이나 push 한 방식이나 차이가 없다.
그렇다. 배열이 아니라 배열의 탈을 쓴 HashMap 이라고 생각해도 좋다. // Javascript의 index 는 그냥 'key'에 불과하다.

가변배열에 push() 로 원소를 추가하는 방식이나 미리 크기를 지정하여 초기화Array()한 방식이나 성능차이가 없다.
사이즈를 반드시 제한할 필요가 없다면 push()를 쓰자. 가독성이 더 좋다
js의 array는 object와 사실상 다를 바가 없다.

Performance를 높이기위해 미리 크기를 선언하고 assign 하는 방식은 다른 컴파일언어에서나 사용하자.
Javascript는 결국 해시맵으로 시작해서 해시맵으로 끝나는 언어다.


🔗 Reference

stackoverflow

profile
I'm still hungry

0개의 댓글