티스토리 뷰
https://nodejs.org/en/docs/guides/dont-block-the-event-loop/
nodejs는 non blocking 이벤트 루프 형태의 시스템을 가지고 있습니다
이런 nodejs의 장점을 살리기 위해서는 메인 이벤트 루프를 blocking 하는 것을 가급적이면 최소화하는것이 시스템의 최고 효율을 낼수 있습니다
메인이벤트루프를 blocking 하는 작업을 실행하면 다른 요청이 들어왔을때 blocking된 작업을 완전히 처리하고 난 뒤에 다음 이벤트가 처리될수 있기때문에 전체적인 시스템의 성능이 저하됩니다
메인 이벤트 루프가 단일쓰레드라 nodejs가 싱글스레드라고 단순히 인식하기 쉬운데요
메인 이벤트 루프는 싱글스레드로 동작하지만,
nodejs는 비싼 작업을 위해 워커 사용하는데 이 워커는 쓰레드풀을 활용합니다
워커를 사용하는 값비싼 작업은 다음과 같습니다
I/O-intensive
DNS: dns.lookup(), dns.lookupService().
File System: All file system APIs except fs.FSWatcher() and those that are explicitly synchronous use libuv's threadpool.
CPU-intensive
Crypto: crypto.pbkdf2(), crypto.scrypt(), crypto.randomBytes(), crypto.randomFill(), crypto.generateKeyPair().
Zlib: All zlib APIs except those that are explicitly synchronous use libuv's threadpool.
그렇기 때문에 위에서 언급된 i/o, cpu intensive한 작업이 있는 서비스를 운영할 경우에는
쓰레드풀의 크기를 늘려 워커를 늘리는것은 서비스의 전체적인 퍼포먼스 향상에 도움을 줍니다
한번 테스트 해볼까요
제 맥북(맥북프로 m1)에서 테스트를 실행해보겠습니다
const crypto = require("crypto");
console.time("thread");
for (let i = 1; i <= 16; i++) {
console.time(`pbkdf2:${i}`);
crypto.pbkdf2("password", "salt", 100000, 512, "sha512", () => {
console.timeEnd(`pbkdf2:${i}`);
});
}
console.timeEnd("thread");
값비싼 예제로 언급되었던 crypto.pbkdf2를 사용하여 암호화를 하는 작업을 해보겠습니다
이작업은 1번의 작업만 했을때 약 400ms의 시간이 소요되는 작업입니다
16번의 pdkdf2 작업을 하는 프로그램을 작성해보았습니다
시작시간과 종료시간을 체크하여 각각의 작업이 언제 끝나는지 확인해보죠
싱글쓰레드의 nodejs를 생각하면 언듯 생각했을때는
1번작업이 끝나면 2번작업이 시작되고 2번작업이 끝나면 3번작업이 시작되는 그런 모습을 생각하셨을수 있습니다
그래서 16개의 모든 암호화 작업이 끝나는 시간이 최종적으로
약 400ms X 16개 = 약 6.4초
이렇게 될것으로 예상하는데요
프로그램을 실행해보겠습니다
4개단위씩 묶어서 숫자가 400ms씩 증가하는것을 볼수 있습니다
4개 단위안에서는 종료시간의 차이가 거의 없습니다
왜 4개씩 차이가 나는걸까요?
이는 4개의 워커가 동작하고 있어서 순차적으로 들어온 작업을 4개의 워커가 나눠서 작업을 했기 때문에
4개의 워커가 작업이 끝나고 다음 4개가 작업이 착수가 된것이라고 볼수 있습니다
이런식의 느낌으로 말이죠
그렇다면 워커의 갯수는 어떻게 늘릴수 있을까요?
UV_THREADPOOL_SIZE 를 프로그램이 실행되기 직전에 선언해줍니다
UV_THREADPOOL_SIZE=8 node index.js
쓰레드를 8개로 늘렸더니 8개 작업마다 시간이 400ms 증가했습니다
그렇다면 1개로 변경해보고 실행해보죠
UV_THREADPOOL_SIZE=1 node index.js
최초에 우리가 생각했던 그러한 시간의 모습이 나왔습니다
약 400ms씩 증가하여 하나씩 순차적으로 완료가 되고 있습니다
그림으로 보자면 이런 느낌이겠죠
이렇듯 nodejs는 쓰레드풀을 사용하여 워커를 사용하고 있습니다
http://docs.libuv.org/en/v1.x/threadpool.html
기본사이즈는 4고 UV_THREADPOOL_SIZE 환경변수를 세팅하여 최대 1024개까지 설정이 가능합니다
(Changed in version 1.30.0: the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024.)
'BACKEND > NODEJS' 카테고리의 다른 글
nestjs @typescript-eslint/no-unused-vars 가 자꾸 괴롭힐때 (0) | 2022.12.08 |
---|---|
nodejs의 논블로킹(non-blocking) 체감하기 (3) | 2022.09.21 |
[nestjs] ClassSerializerInterceptor 전체 적용하기 (0) | 2022.08.10 |
nodejs 프로세스 memory 제한이 있다구요? (0) | 2022.05.23 |
github package로 private npm package 배포하기 (2) | 2022.02.22 |
- Total
- Today
- Yesterday
- 대학생
- 애플
- CSS
- 모바일
- 트위터
- 자바스크립트
- 공모전
- php
- 웹표준
- 안드로이드
- 게임
- AWS
- 창업
- 아이디어
- 스마트폰
- 소프트웨어
- android
- JavaScript
- 앱
- iPhone
- 아이폰
- Apple
- 벤처
- 경진대회
- 구글
- 앱스토어
- 네이버
- 어플리케이션
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |