- 적정 스레드 개수 = cpu 수 * (1+ 대기, 유휴 시간/서비스 시간)
- cpu 대기시간이 서비스 시간보다 짧다면 cpu 개수보다 스레드가 적어야 성능이 좋다.
이유는 대기가 짧기에 (콘텍스트 스위칭 비용이 적기에) 스레드 개수 적어도 상관없다. - 반대로 대기시간이 서비스 처리 시간보다 많다면 스레드 수는 cpu개수보다 많아야 성능이 좋다.
이유는 대기가 길기에 (콘텍스트 스위칭 비용이 많기에) 스레드 개수를 늘려 대기를 줄여야 한다.
- cpu 대기시간이 서비스 시간보다 짧다면 cpu 개수보다 스레드가 적어야 성능이 좋다.
- 스레드를 많이 띄어야 하는 상황
- 대기 시간 즉 cpu가 i/o처리 시 block 걸리는 시간이 길 때 (ex, 대용량 파일 I/O 발생, 긴 네트워크 지연 발생)
에는 스레드 개수를 늘려서 대기시간(block io 시간)을 줄여야 한다. - *block io에 대해 궁금하시면 제 블로글 참조 부탁드립니다.
블로킹/논블로킹, 동기/비동기 I/O 란?
- 대기 시간 즉 cpu가 i/o처리 시 block 걸리는 시간이 길 때 (ex, 대용량 파일 I/O 발생, 긴 네트워크 지연 발생)
- 적정 스레드 풀 개수 = CPU 수 * (CPU 목표 사용량) * (1+대기 시간/서비스 시간)
- ex) Worker 스레드는 요청에 대한 응답을 JSON으로 변환하고 몇 가지 규칙을 실행하는 microservice를 호출한다 가정. 응답 시간은 50ms, 서비스 시간은 5ms이며 worker 스레드를 실행시키는 프로그램은 듀얼코어 cpu라 가정한다면 적절 스레드 풀 사이즈는 2*(1+50/5)=22 가된다.
- 하지만 HTTP 응답 시에는 JMS(자바 메시지 서비스) 로부터의 요청, JDBC Connection Pool과 같은 애플리케이션의 영역을 고려하자면, CPU 사용량을 추가하면 된다. 이때 CPU 목표 사용량은 0~1 사이다.
- 톰캣의 경우 maxThreads로 요청시 처리 스레드의 최대 수 설정 가능하고 maxConnections 수에 도달하면 aceeptCount 설정에 따라 추가 연결은 허용하지만 요청을 처리하지는 않는다.
(가능한 모든 요청 처리 스레드가 사용 중일 때 수신 연결 요청에 대한 최대 대기열 길이. 대기열이 가득 찼을 때 수신 된 모든 요청은 거부됩니다. 기본값은 100이다.)
NIO 및 NIO2는 대기열 기본값이 10000 이고, APR/native는 8192 이다.
- ex) Worker 스레드는 요청에 대한 응답을 JSON으로 변환하고 몇 가지 규칙을 실행하는 microservice를 호출한다 가정. 응답 시간은 50ms, 서비스 시간은 5ms이며 worker 스레드를 실행시키는 프로그램은 듀얼코어 cpu라 가정한다면 적절 스레드 풀 사이즈는 2*(1+50/5)=22 가된다.
- 병렬 Work 스레드의 수(poolSize) 지연 시간(ms) 처리량(TPS) 관계 (시스템 용량 계산)
- (리틀의 법칙) L = λ * W
- L - 동시에 요청된 수 (큐 안에 커넥션 수)
- λ - 평균 도착 시간
- W - 요청이 처리되기까지 평균 대기 시간
- ex) 평균 응답 시간 55ms이며 스레드 풀 크기가 22인 서비스에서 리틀의 법칙 적용하면 22 / 0.055 = 400(TPS) (서비스가 안정적인 응답 시간으로 처리할 수 있는 1초당 요청 수)이다.
- ex) 평균 응답 시간 55ms이며 스레드 풀 크기가 22인 서비스에서 리틀의 법칙 적용하면 22 / 0.055 = 400(TPS) (서비스가 안정적인 응답 시간으로 처리할 수 있는 1초당 요청 수)이다.
- (리틀의 법칙) L = λ * W
- 참고
'운영체제,컴퓨터구조' 카테고리의 다른 글
블로킹/논블로킹, 동기/비동기 I/O란? (0) | 2020.12.15 |
---|---|
멀티스레드를 사용하는 이유 (0) | 2020.12.15 |
프로세스, 스레드의 컨텍스트 스위칭 cpu와의 관계 (0) | 2020.08.08 |
파일 디스크립터란? (0) | 2020.08.08 |
[펌]리눅스 명령어 기초 및 모음 (0) | 2020.03.01 |