개인적으로 저는 지연평가는 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
}
다음은 흔한 짝수만 더하는 로직입니다.
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에 관한 이야기로 찾아뵙겠습니다.