반응형

# worker_threads

  • 노드에서 멀티 스레드 방식으로 작업할 수 있음. (암호화, 압축 작업 말고는 대부분 싱글 스레드를 함)
  • isMainThread : 현재 코드가 메인 스레드에서 실행되는지, 워커 스레드에서 실행되는지 구분
  • 메인 스레드에서는 new Worker를 통해 현재 파일(__filename)을 워커 스레드에서 실행시킴
  • worker.postMessage로 부모에서 워커로 데이터를 보냄
  • parentPort.on('message')로 부모로부터 데이터를 받고, postMessage로 데이터를 보냄
console.log('--------------worker_threads-------------')
const { isMainThread, parentPort } = require('worker_threads');

if (isMainThread) { // 메인스레드
    const worker = new Worker(__filename);
    worker.on('message', (value) => console.log('워커로부터', value));

    worker.postMessage('ping');
} else {    // 워커스레드
    parentPort.on('message', (value) => {
        console.log('부모로부터', value);
        parentPort.postMessage('pong');
        parentPort.close();
    });
}
  • worker 여러개 생성해서 하는 예 (싱글워커)
console.log('--------------worker_threads-------------')
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('워커 끝~');
            }
        });
    }
} else {    // 워커스레드
    const data = workerData;
    parentPort.postMessage(data.start * 100);
}
  • worker_threads 사용 2 ~ 천만 사이 소수찾는 예
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);


출력 결과
prime: 11.416s
664579
  • 각 워커에게 일 분배를 해주는 코드를 짜야함. (멀티 스레드 사용)
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', (err) => {
            throw err;
        });
        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);
}

출력 결과
prime: 1.854s
664579
  • 멀티 스레드를 Node 보다는 다른 언어로 하는게 좋음.

 

# child_process

const exec = require('child_process').exec;

var process = exec('dir');

process.stdout.on('data', function (data) {
    console.log(data.toString());
});

process.stderr.on('data', function (data) {
    console.error(data.toString());
});
  • spawn.js 에서 test.py 호출 예 (단, 다른 언어를 호출 할 때는 해당 언어가 설치되어있어야 함_노드가 실행 요청을 하는 것.)
# spawn.js 파일
const spawn = require('child_process').spawn;

const process = spawn('python', ['test.py']);

process.stdout.on('data', function (data) {
    console.log(data.toString());
});

process.stderr.on('data', function (data) {
    console.error(data.toString());
});



# test.py 파일
print('hello python')


node spawn 실행 시 출력 결과
hello python

 

# 기타 모듈

  • assert : 값을 비교하여 프로그램이 제대로 동작하는지 테스트하는 데 사용.
  • dns : 도메인 이름에 대한 IP 주소를 얻어내는데 사용.
  • net : HTTP 보다 로우 레벨인 TCP 나 IPC 통신을 할 때 사용.
  • string_decoder : 버퍼 데이터를 문자열로 바꾸는 데 사용.
  • tls : TLS와 SSL에 관련된 작업을 할 때 사용.
  • tty : 터미널과 관련된 작업을 할 때 사용.
  • dgram : UDP와 관련된 작업을 할 때 사용.
  • v8 : V8 엔진에 직접 접근할 때 사용.
  • vm : 가상 머신에 직접 접근할 때 사용.

 

 

반응형

+ Recent posts