728x90
노드에서 멀티 스레드 방식으로 작업할 수 있음.


- isMainThread: 현재 코드가 메인 스레드에서 실행되는지, 워커 스레드에서 실행되는지 구분
- 메인 스레드에서는 new Worker를 통해 현재 파일(__filename)을 워커 스레드에서 실행시킴
- worker.postMessage로 부모에서 워커로 데이터를 보냄
- parentPort.on(‘message’)로 부모로부터 데이터를 받고, postMessage로 데이터를 보냄
- new Worker 호출하는 수만큼 워커 스레드가 생성됨
여러개의 워커 스레드
const {Worker, isMainThread, parentPort, workerData} = require('worker_threads');
if(isMainThread){ //메인스레드
const threads = new Set();
threads.add(new Worker(__filename, {
workerData: {start : 1},
}));
threads.add(new Worker(__filename, {
workerData: {start : 2},
}));
for(let worker of threads){
worker.on('message', (value) => {
console.log('워커로부터', value);
})
worker.on('exit', () => {
threads.delete(worker);
if(threads.size === 0) {
console.log('워커 끝~');
}
});
worker.postMessage('ping'); //워커스레드 생성
}
}else{ //워커 스레드
const data = workerData;
parentPort.postMessage(data.start + 100);
}
- workerData를 통해 워커스레드의 데이터를 읽어올 수 있다.
싱글 스레드 (에라스토테네스의 체)
const min = 2;
const max = 10_000_000;
const primes = [];
function generatePrimes(start, range){ //에라스토테네스의 체
let isPrime = true;
const end = start + range;
for(let i = start; i < end; ++i){
for(let j=min; j<Math.sqrt(end); ++j){
if(i !== j && i % j === 0){
isPrime = false;
break;
}
}
if(isPrime){
primes.push(i);
}
isPrime = true;
}
}
console.time('prime');
generatePrimes(min, max);
console.timeEnd('prime');
console.log(primes.length);
- 에라스토테네스의 체 : min ~ max까지 소수를 찾는 프로그램
- 해당 연산은 오래 걸리기 떄문에 실제 서비스를 하기 힘들다 -> 해결책: 워커 스레드
멀티 스레드
const {Worker, isMainThread, parentPort, workerData} = require('worker_threads');
const min = 2;
let primes = [];
function findPrimes(start, range){ //에라스토테네스의 체
let isPrime = true;
const end = start + range;
for(let i = start; i < end; ++i){
for(let j=min; j<Math.sqrt(end); ++j){
if(i !== j && i % j === 0){
isPrime = false;
break;
}
}
if(isPrime){
primes.push(i);
}
isPrime = true;
}
}
if(isMainThread){
const max = 10_000_000;
const threadCount = 8;
const threads = new Set();
const range = Math.ceil((max - min) / threadCount);
let start = min;
console.time('prime');
for(let i = 0; i< threadCount - 1; ++i){
const wStart = start;
threads.add(new Worker(__filename, {workerData:{start:wStart,range}}));
start += range;
}
threads.add(new Worker(__filename, {workerData:{start, range : range + ((max - min + 1) % threadCount)}}));
for( let worker of threads){
worker.on('error',(error) => {
throw error;
});
worker.on('exit', ()=>{
threads.delete(worker);
if(threads.size === 0){
console.timeEnd('prime');
console.log(primes.length);
}
});
worker.on('message', (msg) =>{
primes = primes.concat(msg);
});
}
}else {
findPrimes(workerData.start, workerData.range);
parentPort.postMessage(primes);
}
- worker 스레드의 일을 배분하고, 종합하는 것 모두 이를 사용하는 쪽에서 직접 작성해 주어야 한다(어렵다)
- 시간이 단축된 것을 확인할 수 있다.
- 워커 스레드의 개수를 줄인다고 해서, 꼭 정비례해서 시간이 줄어드는 것은 아니다( 스레드를 생성하는 시간, 코어 갯수 등 여러 변수들도 시간에 영향을 주기 때문에)
728x90
'Node > 노드 기능' 카테고리의 다른 글
| 파일 시스템 사용하기 (0) | 2022.09.04 |
|---|---|
| child_process (0) | 2022.07.24 |
| crypto와 util (0) | 2022.07.24 |
| Url과 querystring (0) | 2022.07.24 |
| os와 path (0) | 2022.07.24 |