io_uring vs epoll

io_uring은 Facebook의 Jens Axboe가 만든 Linux용 새로운 비동기 I/O API로, 유저스페이스와 커널스페이스간에 매핑되는 SQ(요청 큐), CQ(완료 큐) 두가지의 링 버퍼를 사용한다.

https://www.usenix.org/conference/lisa21/presentation/gregg-computing

애플리케이션은 SQ를 통해 커널에게 완료하길 원하는 작업을 SQE(SQ 엔트리)라는 포맷으로 제출한다. CQ를 통해서는 완료된 결과를 확인한다. SQ와 유사하게 완료된 결과도 CQE(CQ 엔트리) 라는 포맷으로 제공된다.  (이때 SQ에 SQE를 제출할때 명시적인 시스템 콜 없이 커널이 직접 SQ를 폴링하도록 하는 것도 가능하다.)

기존에 비동기 입출력에 널리 사용되고 있는 epoll은 파일 디스크립터에 대한 이벤트를 제공하는 방식으로, 결국 이벤트가 발생한 파일 디스크립터를 읽거나 쓰려면 유저스페이스에서 추가적으로 시스템 콜을 수행해야 했다. 그에 비해 io_uring은 작업 실행을 커널로 위임하고, 실행 결과를 유저스페이스와 공유하는 공간인 CQ를 통해 제공하기 때문에 불필요한 복사의 필요성을 제거한다.

멜트다운 취약점 이후 도입된 KPTI(커널 페이지 테이블 분리) 패치로 인해 커널스페이스와 유저스페이스를 이동하는 비용이 상당히 비싸졌기 때문에  io_uring을 통해 시스템 콜을 줄이는 것은 상당한 성능 개선 효과를 가져올 수 있다.