반응형
이번에는 Worker를 썼을때와 쓰지않았을때의 성능을 직접 비교해보도록 하겠다.
단순 노가다 작업을 비교해볼 것이다.
1부터 100억까지 더하기
1부터 100억까지 더하면 js Number타입의 안전한 범위인 2^53-1(9007199254740991)을 넘어서므로, 값보다는 시간에 초점을 맞추고 보면된다.
https://jinho.dev/posts/JS-Number/
그냥 반복문으로 더하기
간단하게 반복문으로 더하는 형태로 비교해보자.
console.time('측정');
let sum = 0;
for (let x = 1; x <= 10000000000; x++) {
sum += x;
}
console.log(sum);
console.timeEnd('측정');
23초가 걸릴 모습을 확인할 수 있다.
멀티스레드 이용하기
메인스레드
10개의 스레드를 사용하여 1~10억까지, 10억1부터 20억까지 .... 하여 100억까지 더하는 코드이다.
worker는 병렬로 작동하므로, 해당 작업이 끝나고 값을 Promise로 받아야 이후 코드에서 잘 이용할 수 있다.
따라서 promises라는 배열을받아 모든 Promise를 받은 후, Promise.all로 병렬처리를 구현했다.
반복문 내부에서 await를 사용하여 처리하면 동기처리가 되므로 병렬처리가 안된다!
import { Worker } from 'worker_threads';
const runWorker = async (data) => {
return new Promise((resolve) => {
const worker = new Worker('./worker.mjs');
worker.on('message', resolve);
worker.postMessage(data);
});
};
const run = async () => {
const WORKER_COUNT = 10; //10개의 스레드로 구성
const promises = [];
let last = 1;
console.time('측정');
for (let x = 1; x <= WORKER_COUNT; x++) {
const data = {
start: last, //1부터 10억, 10억1부터 20억 ....
end: x * 1000000000,
};
last = x * 1000000000 + 1;
promises.push(runWorker(data)); //반환된 프로미스를 promises에 push
}
const results = await Promise.all(promises);
console.log(results.reduce((acc, cur) => acc + cur, 0)); //합계 계산하여 출력
console.timeEnd('측정');
};
run();
worker스레드
단순히 시작값 부터 끝값까지 더해주는 역할을 한다.
import { parentPort } from 'worker_threads';
parentPort.on('message', ({ start, end }) => {
let sum = 0;
for (let x = start; x <= end; x++) {
sum += x;
}
parentPort.postMessage(sum);
parentPort.close();
});
단 2초만에 끝난 모습이다.
스레드가 10개라 정말 딱 10배정도의 차이가 난다!!
반응형