지연평가, Generator? Iterator?

오병진·2022년 4월 26일
0

FxTs

목록 보기
2/4

개인적으로 저는 지연평가는 ES6+, 즉 모던 JS에서의 핵심이라고도 생각합니다.
상황에 따라서 속도는 상이하지만, 필요할 때 메모리를 끌어서 사용한다는 점은
분명 매력적이죠.

여러 예제를 한번 살펴봅시다.

function solution1(size){
  function newArr(n) {
    let i = 1;
    const res = [];
    while (i < n) res.push(i++);
    return res;
  }

  let sum = 0;
  const numArr = newArr(size);
  for(let i = 0; i < numArr.length; i++){
    if(numArr[i] % 2 === 0){ sum += numArr[i]; }
    else if(sum >= 100) break;
  }
  return sum // expected 6
}

다음은 흔한 짝수만 더하는 로직입니다.

generator

numArr이 먼저 선언됨으로써 메모리를 잡아먹고있습니다.
이를 한번 수정해보겠습니다.

function solution2(size){
  function * numArr(n){
    let i = 1;
    while (i < n) yield i++;
  }

  let sum = 0;
  for(const item of numArr(size)){
    if(item % 2 === 0){ sum += item; }
    else if(sum >= 100) break;
  }
  return sum; // 6
}

코드는 더 늘어났지만 수행시간은 상당히 짧아졌습니다.
사실 티가 안날테니 시간을 재보도록 하겠습니다.

시간 체크

console.time('');
console.log("solution1 : ", solution1(10000)); // solution1 : 110
console.timeEnd(''); // 0.581054...

console.time('');
console.log("solution2 : ", solution2(10000)); // solution2 : 110
console.timeEnd(''); // 0.1940917...

10000개로 하니 대략적으로 세배차이가 나네요.
더 극단적으로 올려보겠습니다.

console.time('');
console.log("solution1 : ", solution1(10000000)); // solution1 : 110
console.timeEnd(''); // 134.38 ms

console.time('');
console.log("solution2 : ", solution2(10000000)); // solution2 : 110
console.timeEnd(''); // 0.123 ms

선제적으로 선언하는 즉시평가가 이리 메모리를 잡아먹는 것을 알 수 있습니다.
물론 배열 전체를 다 사용한다면 먼저 선언하는게 더 빠릅니다 허헛...

// exclude else if
console.time('');
console.log("solution1 : ", solution1(10000)); // solution1 : 24995000
console.timeEnd(''); // 1.74ms

console.time('');
console.log("solution2 : ", solution2(10000)); // solution2 : 24995000
console.timeEnd(''); // 2.55ms

특정 구간까지 도는, 즉 조건문이 있고 take 옵션 등이 있다면
차라리 선제적으로 선언하는 즉시평가가 더 효율이 좋다.

다음에는 if와 filter에 관한 이야기로 찾아뵙겠습니다.

profile
지나가는 사람입니다. 마저 지나갈게요 :D

0개의 댓글