본문 바로가기

3.구현/HTML5&Javascript

[javascript] Underscore 성능

들어가기

Unserscore는 함수형 프로그래밍을 지원하는 자바스크립트 라이브러리입니다. 성능을 좀더 향상하고 효율적으로 처리하기 위해서 많이 사용하고 있습니다. 성능에 대해 조금 다룰려고 합니다.

작성자: ospace114@empal.com, http://ospace.tistory.com/

데이터 구조

사용할 데이터 구조는 다음과 같다.

fig 01. 데이터 구조

contents 배열이 있고, contents안에 다시 files 배열이 있다. 여기서 원하는 부분은 files 배열안에 있는 file_id를 배열 형태로 추출하고 싶다.

Underscore로 추출

Underscore로 file_id를 추출할 수 있는 방법이 몇가지가 있다.

방법1

먼저 reduce(), union(), map()을 활용해보자.

var a = _.reduce(contents, function(r,c) {
    return _.union(r, _.map(c.files, function(f){
        return f.file_id;
    }))
}, []);

reduce()에 의해서 개별 contents를 추출한다. 다시 이를 map()으로 넘겨서 개별 contents의 files을 각각 넘긴다. 그러면 파일에 있는 file_id를 리턴한다. map()에 의해서 배열로 만들어진다. 그러면 각 contents별로 file_id가 저장된 배열 들이 생성된다. 이를 union()으로 하나의 배열로 합친다.
이 방법의 실행시간은 약 5.39 msec이다.

방법2

다음은 flatten(), map()을 사용하였다.

var b = _.flatten(_.map(contents, function(c){
    return _.map(c.files, function(f){
        return f.file_id;
    });
}));

첫번 째 map()에 의해서 contents 별로 처리 시작한다. 그리고 다음 map()에서 개별 contents의 files 들을 각각 처리한다. 두번째 map()에서 files의 file_id를 리턴해서 배열로 만든다. 그리고 첫번째 map()에 의해서 file_id 배열을 다시 배열로 묶어서 리턴한다. 2차원 배열 형태로 되었다. 이를 flatten()에 의해서 1차원 배열로 만든다.

이 방법의 실행시간은 약 0.561 msec이다.

방법3

다음은 reduce()만 사용했다.

var c = _.reduce(contents, function(r,c) {
    return _.reduce(c.files, function(r2, f){
        r2.push(f.file_id);
        return r2;
    }, r);
}, []);

첫번째 reduce()에 의해서 개별 contents를 처리하고 두번째 reduce()에 의해서 contents의 개별 files을 처리한다. 두번째 reduce()에서 files의 file_id를 추출해 결과에 추가한다. 결과가 추가되는 배열은 첫번째 reduce()에서 받을거라 결국 최종 결과가 저장되는 배열이 된다.

이 방법의 실행시간은 0.359 msec이다.

Vanilla JS

다음은 순수 자바스크립트만 사용했다.

var ids = [];
for(var it in contents) {
    for(var it2 in contents[it].files) {
        ids.push(contents[it].files[it2].file_id);
    }
}

코드 자체는 직관적이다. contents의 files의 file_id를 ids 배열에 저장한다.

이 방법의 실행시간은 0.157 msec이다.

결론

각 방법의 실행시간을 정리하면 다음과 같다.

  • Underscore 방법1: 5.39 msec
  • Underscore 방법2: 0.561 msec
  • Underscore 방법3: 0.359 msec
  • Vanilla JS 방법: 0.157 msec

Underscore는 어떻게 해도 Vanilla JS을 넘을 수 없었다. 물론 앞의 예가 Underscore에 적합하지 않은 경우일 수 있다. 아니면 저의 실력 부족으로 더 좋은 방법을 찾지 못할 수도 있다. 그러나 Vanilla JS을 사용한 방법이 가장 좋았다.
결론적 Underscore가 성능적으로 항상 좋지는 않고, 그리고 어떻게 처리하는가에 의해서 Underscore 내에서도 성능차이가 크게 난다. 결국 Underscore을 적용하지 못했다.
한 가지 아쉬운 부분은 사용했던 데이터와 실제 데이터 크기 정보를 기록하지 못해서 좀더 정확한 비교를 하지 못했다는 아쉬움이 있다.
혹시나 해서 Underscore가 안 좋은 라이브러리로 받아 들일 수 있을 것 같네요. Underscore는 Javascirpt에서는 부족한 함수형 프로그래밍에 풍부한 기능이 제공되고 있습니다. 혹시나 관심있으신 분은 참고하시기 바랍니다.
부족한 글이지만 여러분에게 도움이 되었으면 합니다. 모두 즐거운 코딩생활 되세요.^^ ospace.

참고

[1] underscore.js, http://underscorejs.org

반응형