컨텍스트 스위칭 비용과 원리
한 줄 정의
컨텍스트 스위칭은 CPU가 현재 실행 중인 프로세스/스레드의 상태를 저장하고, 다음 프로세스/스레드의 상태를 복원하는 과정이다.
실무에서 왜 중요한가
컨텍스트 스위칭을 이해하지 못하면 다음 문제가 생긴다.
- 스레드를 과도하게 생성해서 실제 작업 시간보다 전환 비용이 더 크다.
- CPU 사용률은 높은데 처리량(throughput)이 낮은 원인을 모른다.
- 프로세스 간 전환과 스레드 간 전환의 비용 차이를 모른다.
동작 과정
Thread A 실행 중
│
├─ 1. Thread A의 레지스터, PC, 스택 포인터를 PCB/TCB에 저장
│
├─ 2. 스케줄러가 다음 실행할 Thread B 선택
│
├─ 3. Thread B의 저장된 상태를 레지스터에 복원
│
└─ 4. Thread B 실행 재개
소요 시간: 수 마이크로초 (µs)
직접 비용 vs 간접 비용
| 구분 | 내용 |
|---|---|
| 직접 비용 | 레지스터 저장/복원, 커널 모드 전환 (~수 µs) |
| 간접 비용 | CPU 캐시 무효화 (Cache Miss 증가), TLB Flush |
간접 비용이 더 크다. 전환 후 새 스레드가 사용하는 데이터가 캐시에 없으면 메모리에서 다시 로드해야 한다.
프로세스 vs 스레드 컨텍스트 스위칭
| 구분 | 프로세스 전환 | 스레드 전환 (같은 프로세스 내) |
|---|---|---|
| 메모리 공간 | 전환 (Page Table 변경) | 공유 (변경 없음) |
| TLB | Flush 필요 | Flush 불필요 |
| 캐시 | 대부분 무효화 | 일부 유지 |
| 비용 | 높음 | 낮음 |
같은 프로세스 내 스레드 전환은 메모리 공간이 같으므로 비용이 훨씬 작다.
컨텍스트 스위칭 모니터링
# 시스템 전체 컨텍스트 스위칭 횟수
vmstat 1
-----procs--- ---system---
r b in cs
3 0 1200 15000 ← cs: 초당 컨텍스트 스위칭 횟수
# 프로세스별 컨텍스트 스위칭
pidstat -w -p <PID> 1
# cswch/s: 자발적 (I/O 대기 등)
# nvcswch/s: 비자발적 (Time Quantum 초과, 우선순위 선점)| 지표 | 의미 | 주의 |
|---|---|---|
| voluntary (cswch) | 자발적 전환 (I/O 대기, sleep) | I/O 바운드 작업에서 정상 |
| involuntary (nvcswch) | 비자발적 전환 (OS가 강제 선점) | 높으면 CPU 경합 |
컨텍스트 스위칭을 줄이는 방법
- 적절한 스레드 수: CPU 코어에 비해 스레드가 너무 많지 않게
- 스레드 풀 사용: 스레드 생성/소멸 반복 방지
- 비동기 I/O: I/O 대기 시 스레드를 반환해서 전환 횟수 감소
- Virtual Thread (Java 21): OS 스레드 수를 줄여서 전환 비용 감소
전통적 모델 (Thread-per-Request):
200 요청 → 200 OS 스레드 → 빈번한 컨텍스트 스위칭
Virtual Thread:
200 요청 → 200 Virtual Thread → 소수의 OS 스레드(carrier)
→ I/O 대기 시 Virtual Thread만 교체, OS 스레드는 유지
→ OS 레벨 컨텍스트 스위칭 감소
자주 나는 실수
- 스레드를 무한히 늘리면 처리량이 비례해서 늘어난다고 생각한다.
- 컨텍스트 스위칭을 무시하고 스레드 수만 늘려서 오히려 성능이 떨어진다.
- 자발적/비자발적 전환을 구분하지 않고 원인 분석을 한다.
- 스레드 풀 사이즈를 줄였는데 I/O 대기가 원인이어서 효과가 없다.
핵심 요약
컨텍스트 스위칭은 CPU가 실행 대상을 전환할 때 발생하며, 직접 비용(레지스터 저장/복원)보다 간접 비용(캐시 무효화)이 더 큽니다. 같은 프로세스 내 스레드 전환은 프로세스 전환보다 비용이 작습니다.
스레드가 과도하면 전환 비용이 누적되어 처리량이 오히려 떨어집니다.
vmstat의 cs, pidstat의 cswch/nvcswch로 모니터링하고, 적절한 스레드 수와 비동기 I/O로 최적화합니다.
꼬리 질문
컨텍스트 스위칭이 많으면 어떤 증상이 나타나는가?
CPU 사용률은 높지만 처리량(throughput)이 낮아집니다.
top에서%sy(system)가 높으면 커널에서 전환 비용이 많이 소모되고 있다는 의미입니다.
I/O 대기로 인한 컨텍스트 스위칭은 나쁜가?
자발적 전환 자체는 정상입니다. I/O를 기다리는 동안 다른 스레드가 CPU를 사용할 수 있으므로 효율적입니다. 문제는 너무 많은 스레드가 I/O를 기다려서 전환이 빈번해지는 경우입니다.
Virtual Thread가 컨텍스트 스위칭을 줄이는 원리는?
Virtual Thread는 I/O 대기 시 OS 스레드(carrier)를 반환하고, JVM 내부에서 다른 Virtual Thread를 같은 carrier에 배정합니다. OS 레벨의 전환 없이 JVM 내부에서 경량 전환이 일어나므로 비용이 훨씬 작습니다.