이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
Scheduling과 Context Switch 비용에서 붙잡아야 할 핵심 판단 기준은 무엇인가?전환 비용은 thread가 많아질수록 숨은 지연이 된다라는 기준은 어떤 JVM/OS 신호로 확인되는가?- Java/Spring 코드에서
Scheduling과 Context Switch 비용판단 기준은 어떤 장애 신호로 드러나는가?
개요
이 문서의 주제는 Scheduling과 Context Switch 비용이다. OS scheduler가 runnable thread를 CPU에 올리는 방식과 context switch 비용을 다룬다.
먼저 붙잡을 기준은 다음 문장이다. 전환 비용은 thread가 많아질수록 숨은 지연이 된다. 이 문서는 이 기준을 Java/Spring 실행 흐름, JVM/OS 관찰 지표, 장애 판단 순서로 연결한다.
핵심 모델
- 판단 기준: 실행 후보가 많아질수록 scheduler 비용도 비용이 된다.
- Context switch는 CPU가 한 실행 흐름에서 다른 실행 흐름으로 바뀌는 비용이다.
- Voluntary switch는 I/O 대기나 sleep처럼 스스로 물러나는 경우가 많고, non-voluntary switch는 CPU time slice 경합과 관련된다.
- Runnable thread가 많고 CPU quota가 낮으면 작업은 많아 보여도 실제 실행 시간은 잘게 쪼개진다.
- Context switch 증가는 원인일 수도 있고 blocking I/O 증가의 결과일 수도 있어 stack과 함께 해석해야 한다.
문서별 핵심 구분
- scheduler는 runnable thread를 CPU core에 배치한다.
- context switch는 작업 전환 비용이며 thread가 많을수록 무시하기 어렵다.
- blocking과 wake-up이 잦으면 CPU를 많이 쓰지 않아도 지연이 커질 수 있다.
원리
Scheduler는 runnable thread를 CPU core에 배치한다. runnable thread가 core보다 많으면 모든 thread가 동시에 실행되는 것이 아니라 짧은 시간 조각을 나눠 받는다.
Context switch는 실행 중인 thread를 멈추고 다른 thread의 register, stack, scheduler 상태로 바꾸는 비용이다. 한 번의 비용은 작아 보여도 thread가 많고 blocking/wake-up이 잦으면 latency와 CPU overhead로 누적된다.
Java 서버에서는 blocking I/O, 짧은 timeout, 즉시 retry, 너무 큰 worker pool, 과도한 logging이 wake-up을 늘릴 수 있다. CPU 사용률이 높지 않아도 runnable queue와 context switch가 늘면 요청 지연이 커진다.
Scheduling과 Context Switch 비용 관점에서 중요한 점은 thread 수 증가를 처리량 증가로 바로 해석하지 않는 것이다. core 수, runnable 개수, voluntary/non-voluntary context switch, load average, thread dump를 함께 봐야 한다.
Java/Spring 연결
- 짧은 작업을 너무 많은 executor에 쪼개면 실제 업무보다 scheduling 비용이 커질 수 있다.
- Tomcat worker,
@Async, scheduler, batch executor가 모두 CPU를 나눠 쓰면 run queue가 길어진다. - Lock 경합이나 DB 대기가 많으면 thread state 변화와 context switch가 함께 늘 수 있다.
- Container CPU quota가 낮은데 thread pool만 키우면 latency tail이 길어진다.
- Thread dump와
pidstat -w를 같이 보면 Java stack과 switch 증가 시점을 연결할 수 있다.
코드와 설정 예시
ThreadPoolExecutor executor = new ThreadPoolExecutor(
200, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>()
);예시는 큰 thread pool이 항상 빠른 처리를 의미하지 않는다는 점을 보기 위한 것이다. core 수보다 훨씬 많은 worker가 runnable 상태로 깨어나면 scheduler 대기와 context switch가 늘고, queue가 무제한이면 지연이 안쪽에 쌓일 수 있다.
관찰 명령
vmstat 1 5
pidstat -w -p <pid> 1 5
top -H -p <pid>
cat /proc/<pid>/sched | headScheduling과 Context Switch 비용 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.
지표 해석
| 신호 | 먼저 의심할 것 | 다음 확인 |
|---|---|---|
| RUNNABLE thread가 core보다 많음 | CPU 경합 또는 native I/O 대기 | top -H, stack trace, load average |
| BLOCKED가 특정 lock에 몰림 | synchronized/monitor 경합 | lock owner와 기다리는 thread |
| WAITING/TIMED_WAITING이 pool에 몰림 | queue 대기, connection 대기, sleep/retry | executor, Hikari, timeout 지표 |
| thread 수가 계속 증가 | unbounded executor 또는 thread leak | thread name 분포와 생성 위치 |
Scheduling과 Context Switch 비용에서는 핵심 신호와 보조 지표를 같은 시간축에서 맞춘다. 먼저 변한 신호와 뒤따라 포화된 신호를 분리해야 원인과 결과를 구분할 수 있다.
장애 상황에서 보는 순서
vmstat나pidstat -w로 context switch 증가 여부를 본다.- load average와 runnable thread 수를 CPU quota와 비교한다.
- thread dump에서 RUNNABLE, BLOCKED, WAITING 분포와 반복 stack을 확인한다.
- 최근 executor size, batch 동시성, retry 정책 변경을 확인한다.
- thread 수를 늘리는 대신 작업량, queue, timeout, lock 경계를 먼저 조정한다.
이 순서는 context switch를 독립 지표가 아니라 Java 실행 구조의 결과로 읽기 위한 루틴이다.
실전 팁
vmstat의 context switch와 run queue를 함께 본다.- worker thread 수를 늘릴 때 context switch 변화를 확인한다.
- 짧은 작업을 너무 잘게 쪼개면 scheduling 비용이 커질 수 있다.
- CPU 사용률과 load average를 같이 해석한다.
- GC, logging, retry 폭주가 scheduling 압박을 만들 수 있다.
주니어 팁
Scheduling과 Context Switch 비용주제는 용어 암기에서 끝내지 말고, 정상 상태와 장애 상태에서 같은 명령을 실행해 차이를 비교한다.- 처음에는
Scheduling과 Context Switch 비용를 재현 가능한 기본 명령과 Actuator 지표로 확인하는 습관부터 만든다. Scheduling과 Context Switch 비용숫자는 크기 자체보다 평소 기준선에서 얼마나 벗어났는지로 판단한다.
시니어 팁
Scheduling과 Context Switch 비용주제의 영향이 pool, queue, retry, timeout으로 번지는 경로를 설계 리뷰에 포함한다.Scheduling과 Context Switch 비용runbook에는 실행 명령, 정상 범위, 해석 기준, 금지할 대응을 같이 둔다.Scheduling과 Context Switch 비용판단이 container, LB, 다중 인스턴스 환경에서도 같은 의미인지 확인한다.
Guru급 팁
Scheduling과 Context Switch 비용주제는 단일 snapshot보다 변화 방향이 중요하다. 같은 명령을 간격을 두고 실행해 상태가 증가, 유지, 회복 중 어디인지 본다.- 고급 도구는
Scheduling과 Context Switch 비용가설을 좁힐 때만 사용하고 기본 지표와 모순되는지 먼저 확인한다. Scheduling과 Context Switch 비용조치 후에는 CPU, memory, socket, disk, pool 중 다음 포화 지점이 어디로 이동했는지 확인한다.
위험 신호!
- context switch 비용을 0으로 가정한다.
- thread pool을 크게 잡고 queue 대기만 줄었다고 성공으로 판단한다.
- load average를 CPU 사용률과 같은 뜻으로 본다.
- 짧은 timeout과 즉시 retry가 wake-up 폭주를 만드는 점을 놓친다.
- scheduler 지표 없이 thread 수만 튜닝한다.
확인 질문
확인 질문
Scheduling과 Context Switch 비용주제를 장애 중 확인할 때 Application 로그만으로 부족한 이유는 무엇인가?
- 로그는 코드 경로를 보여 주지만
Scheduling과 Context Switch 비용의 JVM/OS 자원 상태, 대기 위치, 포화 방향은 별도 지표로 확인해야 하기 때문이다.Scheduling과 Context Switch 비용관련 설정이나 pool 크기를 바꾸기 전에 확인할 것은 무엇인가?
- 먼저 변한 신호, 하위 자원 capacity, 변경이 완화인지 증폭인지 판단할 기준을
Scheduling과 Context Switch 비용지표로 확인해야 한다.Scheduling과 Context Switch 비용재발을 막기 위해 장애 기록에 무엇을 남겨야 하는가?
- 발생 시간, 영향 범위, 사용한 명령,
Scheduling과 Context Switch 비용핵심 지표, 원인 판단, 완화 조치, 근본 수정, 남은 리스크를 남긴다.