Interrupt에서 Polling, 그리고 Adaptive 기법까지
배경 읽기 자료애플리케이션이 디스크에 데이터를 읽기/쓰기할 때, 요청을 보낸 후 완료를 어떻게 통보받느냐가 I/O completion입니다.
과거 HDD 시대에는 디스크 하나의 I/O에 수 밀리초(ms)가 걸렸으므로, 완료 통보 방식에 따른 수 마이크로초(us)의 차이는 무시할 수 있었습니다. 하지만 현대 NVMe SSD는 하나의 I/O를 10~100 마이크로초(us) 안에 처리합니다.
| 장치 | I/O latency | completion 오버헤드 비율 |
|---|---|---|
| HDD | ~5,000 us | <0.1% (무시 가능) |
| SATA SSD | ~100 us | ~5% |
| NVMe SSD (TLC) | ~15 us | ~30% |
| Intel Optane (3D XPoint) | ~10 us | ~50% |
디바이스가 빨라질수록 소프트웨어 오버헤드가 전체 I/O 시간에서 차지하는 비율이 급격히 증가합니다. I/O completion 방식의 최적화가 곧 전체 I/O 성능의 최적화인 시대가 되었습니다.
I/O 요청 후 CPU를 반납하고 잠듦
디바이스가 완료 시 인터럽트로 깨움
CPU 효율적
깨어나는 비용이 큼
I/O 요청 후 계속 확인 (busy-wait)
완료 즉시 감지 가능
최저 latency
CPU 100% 점유
일정 시간 잠들고, 이후 polling
상황에 따라 모드를 동적 전환
latency와 CPU 사이의 균형
NVMe 드라이버에 poll_queues 파라미터 도입. 하드웨어 큐를 polling 전용으로 분리.
블록 레이어에 blk_poll() API 추가. io_poll sysfs 인터페이스 등장.
Hybrid polling 도입 (io_poll_delay). 일정 시간 sleep 후 polling 시작.
io_uring 등장. 비동기 I/O의 새로운 표준. IORING_SETUP_IOPOLL 플래그로 polling 지원.
preadv2(RWF_HIPRI) 기반 동기식 Direct I/O polling이 안정적으로 동작하는 마지막 시기.
동기식 DIO polling 제거. Polling은 io_uring 전용으로 전환. RWF_HIPRI를 통한 sync polling 경로 삭제.
io_uring이 polling의 주된 인터페이스로 자리잡음. HP(Hewlett Packard Enterprise)가 io_uring 기반 스토리지 스택을 제품에 채택하며 산업계 관심 증가.
preadv2 + RWF_HIPRI)은 커널 유지보수 부담에 비해 사용자가 적었습니다.
io_uring이 더 효율적인 polling 인터페이스를 제공하면서, 중복 경로를 정리하는 차원에서 삭제되었습니다.
그러나 이 결정은 "polling이 불필요하다"는 뜻이 아니라, "polling의 인터페이스가 io_uring으로 통합된 것"입니다.
2026년 2월 개최된 USENIX FAST '26 (File and Storage Technologies 학회)에서 I/O completion 최적화에 관한 논문이 복수 발표되며, 이 분야의 연구가 다시 활발해지고 있음을 보여주었습니다.
"DPAS: A Prompt, Accurate and Safe I/O Completion Method for SSDs"
"UnICom: A Universally High-Performant I/O Completion Mechanism for Modern Computer Systems"
| 관점 | DPAS | UnICom |
|---|---|---|
| 모드 결정 신호 | I/O 큐 깊이 (qd) — I/O 행위 직접 계수 | run queue task 수 — CPU 경쟁 간접 추정 |
| polling 주체 | I/O를 요청한 쓰레드 본인 | 전용 completion thread (다른 코어) |
| 커널 수정 범위 | 블록 레이어 + NVMe 드라이버 | 스케줄러 + 별도 커널 모듈 |
| single I/O + 다수 C-thread | qd=1 → CP (최적) | task>1 → TagSched-TagPoll (불필요 오버헤드) |
switch_stat sysfs 인터페이스로 확인할 수 있습니다.
Linux 5.0에서 등장한 io_uring은 현재 Linux I/O의 핵심 인터페이스로 자리잡았습니다.
커널과 유저스페이스 사이에 공유 링 버퍼(Submission Queue, Completion Queue)를 두어, 시스템 콜 없이 I/O 요청을 제출하고 완료를 확인할 수 있는 비동기 I/O 프레임워크입니다.
기존 방식: App → syscall → 커널 → 디바이스 → 인터럽트 → 커널 → syscall 리턴 → App
io_uring: App → SQ에 기록 → 커널이 처리 → CQ에 기록 → App이 CQ 확인
(syscall 최소화, 배치 처리 가능)
io_uring의 IORING_SETUP_IOPOLL 모드는 completion을 polling으로 확인합니다.
동기식 DIO polling이 5.19에서 제거된 후, io_uring이 polling의 유일한 공식 인터페이스가 되었습니다.
DPAS와 같은 adaptive completion 기법이 io_uring의 polling 경로에 통합된다면, workload에 따라 자동으로 최적의 completion 모드를 선택하는 것이 커널 수준에서 가능해집니다. 이는 커널 mainline 채택의 유력한 경로로 논의되고 있습니다.
이 실습에서 커널 5.18을 사용하는 이유는 다음과 같습니다:
preadv2(RWF_HIPRI)를 통한 sync polling이 동작하는 마지막 커널입니다. 5.19부터 이 경로가 제거되었습니다.Guest (kernel 5.18) Host (kernel 5.19+, macOS, Windows...)
───────────────── ──────────────────────────────────────
App: preadv2(RWF_HIPRI)
│
Guest NVMe driver: REQ_POLLED 설정
│
Guest: poll CQ (busy-wait) ◄── guest 내부에서 완결
│ ▲
가상 NVMe CQ ◄──── QEMU가 CQ entry 기록 ◄── Host I/O 완료
Documentation/block/queue-sysfs.rst (io_poll, io_poll_delay)io_uring(7) man page, Jens Axboe의 "Efficient IO with io_uring"drivers/nvme/host/pci.c (nvme 모듈 파라미터)