자바스크립트 성능 최적화에 대한 의문이 들었다

재미있는 서비스를 발견했다

자바스크립트를 공부하던 중 재미있는 서비스를 하나 발견했다.

JSBEN.CH Performance Benchmarking Playground for JavaScript

자바스크립트 코드의 벤치마크 테스트를 할 수 있는 서비스인데
여러개의 자바스크립트 코드블럭들을 추가해 놓고,
run tests 버튼을 누르면 각 코드블럭들에 대해 벤치마크를 진행한다.

구조를 살펴보니 같은 코드를 수만번 반복 후 실행시간을 측정하는 것 같다

결과는 아래와 같이 나오는데

벤치마크 결과 예시

실행속도가 가장 긴 블럭의 실행시간을 100%로 표시하고
나머지 블럭들의 실행시간을 100%에 대한 상대적인 백분율로 표시한다.

for문과 while문 중에 뭐가 더 빠를까?

따위의 질문에 대해 간단하게 테스트해볼 수 있는 서비스인 것이다.

직접 벤치마크를 만들어보았다

목표

숫자형 값들로만 이루어진 배열이 있고,
해당 배열의 각 요소의 제곱한 값으로 이루어진 새로운 배열을 만들어내는 코드를 작성한다고 했을 때

다양한 방법들로 구현해낼 수 있을 것이다.

이 다양한 방법들의 실행속도를 동일한 조건하에서 상호 비교해 보는 테스트를 만들어보는 것이 목표이다.

초기화 코드

초기화 코드는 테스트의 실행 전에 매번 실행되는 코드 블럭이다.
초기화 코드의 실행시간은 벤치마크 결과에 반영되지 않는다.

내가 만든 테스트의 초기화 코드는 아래와 같다.

const a = [1,2,3,4,5,6,7,8,9,10,11];

보일러플레이트

각 테스트의 실행 전에 매번 실행되는 코드 블럭이라는 점은 초기화 코드와 동일하지만,
이 코드는 벤치마크 결과에 반영이 된다.

각 테스트 코드들에 사용할 데이터를 초기화하는 용도로 사용한다.

내가 만든 테스트의 보일러플레이트는 아래와 같다.

let arr = [];

테스트 코드들

벤치마크에 사용될 코드들이다.

주로 같은 결과값을 내놓는 코드들을 등록해 놓고

상호간의 실행시간을 비교하게된다.

map

arr = a.map(n => n*n);

forEach

a.forEach(n => arr.push(n*n));

for of

for (const one of a) {
    arr.push(one * one);
}

original for

for (let i = 0; i < a.length; i++) {
    arr.push(a[i] * a[i]);
}

original for (배열길이 캐싱)

const l = a.length;

for (let i = 0; i < l; i++) {
    arr.push(a[i] * a[i]);
}

original for (배열 길이와 현재값 캐싱)

const l2 = a.length;

for (let i = 0; i < l2; i++) {
    const now = a[i];
    arr.push(now * now);
}

실행결과

위 테스트를 크롬 브라우저에서 실행했을때 결과는 다음과 같다.

크롬에서의 실행결과

위 결과를 해석해보면 다음처럼 해석할 수 있다.

map이랑 forEach는 되게 느리고 for of가 가장 빠르네~
for문을 사용할 때는 배열 길이는 캐싱해놓고 돌리는게 빠르겠구나~

앞으로 배열 요소들을 순차적으로 접근할 때는 for of 문을 사용해야겠다.

그러나..

아래 이미지는 똑같은 테스트를 파이어폭스에서 실행한 결과를 캡처한 것이다.

파이어폭스에서의 결과

전반적으로 비슷한 양상을 보이지만, 각 결과의 차이가 훨씬 크다.

오리지널 for문이나 for of 문의 경우 크롬보다도 빠른 실행속도를 보여줬으나,
map이나 forEach문의 경우 크롬보다 훨씬 느렸다.

삼성인터넷브라우저 - 갤럭시S10 5G

갤럭시S10 삼성인터넷브라우저에서의 결과

위 이미지는 내 스마트폰(갤럭시S10 5G) 모델에서 삼성브라우저를 이용해 진행한 동일한 테스트코드의 벤치마크 결과이다.

직전 두 개의 브라우저의 결과와는 사뭇(?) 다른 결과가 도출되었다..

결론

똑같은 코드여도 실행환경에 따라 퍼포먼스는 천차만별이다.

각기다른 자바스크립트 엔진을 사용하는 브라우저가 서로 다른 결과를 내는 것은 어쩌면 아주 당연한 일일지도 모른다.

구현방법에 대한 표준화가 딱히 이루어져있는 것은 아닐테니까 말이다.

한편으로는 구조적인 측면이 아닌 문법적인 측면에서 가장 빠른 실행구문을 찾아내는 일이 어쩌면 사실상 무의미한 일일지도 모른다라는 생각이 들었다.

물론 자바스크립트 뉴비로써 부족한 식견에 섣불리 내린 결론이니, 고수님들이 이 글을 보신다면 피와 살이되는 조언을 부탁드리겠다.

직접 만든 테스트코드들

http://jsben.ch/6Sb18 <- 본문에 활용된 테스트

http://jsben.ch/KfaCH <- indexOf, for of, findIndex에 대한 벤치마크도 만들어봤다.

http://jsben.ch/MN7c2 <- 배열에 요소를 추가하는 세가지 방법에 대한 벤치마크.

http://jsben.ch/YKqOq <- reduce, forEach, for of 벤치마크

http://jsben.ch/JYDla <- 배열 이어붙이기 벤치마크