Redox OS - Ring Buffers Project Summary
Redox OS 링 버퍼 프로젝트 요약
Redox OS 팀이 애플리케이션과 시스템 서비스 사이의 비동기 I/O를 위한 Redox Rings를 구현했습니다. 공유 메모리로 데이터 복사를 줄이고, 동기식 시스템 호출 대비 14~15배 빠른 벤치마크를 제시했으며 IPC 지연도 약 5800사이클에서 2700사이클로 낮췄습니다.
- 주제
에디터 노트
이번 성과에서 설득력 있는 부분은 링 버퍼 자체의 속도 수치와 IPC 개선을 구분해 제시한 점입니다. Redox Rings 벤치마크는 동기식 호출보다 14~15배 빠르지만, 글도 실제 작업 부하에서의 비용 분포는 추가 조사가 필요하다고 밝힙니다. 따라서 이 수치를 일반적인 애플리케이션 성능 향상으로 확대하기보다 비교한 벤치마크의 결과로 읽는 편이 정확합니다. Redox Rings는 커널이 큐를 중개하는 Linux io_uring과 달리 애플리케이션이 사용자 공간 scheme에 직접 요청을 보냅니다. 공유 메모리로 데이터 복사를 없애는 대신 큐와 버퍼 풀, 세션 관리가 양쪽 프로세스에 걸칩니다. 댓글은 제로카피의 가치와 구현 난도를 긍정하지만 구체적인 검증이나 반론을 보태지는 않습니다. 이번 수치에서 링 버퍼의 기여분과 별도로 진행한 IPC 최적화의 기여분은 분리해 제시하지 않았습니다.
AI 요약
Redox OS 팀은 NLnet Foundation과 NGI Zero Commons Fund 등의 지원으로 시스템 서비스와 드라이버에서 사용할 링 버퍼 통신을 구현했습니다. 이번 단계는 9월에 마무리됐으며, 애플리케이션용 API와 지원 크레이트, 드라이버용 비동기 실행기, 커널 IPC 최적화가 포함됩니다.
Redox Rings와 공유 메모리
Linux의 io_uring은 애플리케이션이 커널에 I/O 작업을 제출하는 인터페이스입니다. Redox는 마이크로커널 구조라 파일 I/O 요청을 사용자 공간의 scheme 프로세스가 처리합니다. Redox Rings는 애플리케이션이 해당 scheme에 직접 비동기 요청을 보내도록 설계했습니다. 커널이 링 큐에 접근하지 않으며, 요청을 주고받는 SQ(submission queue)와 CQ(completion queue)는 애플리케이션과 scheme이 공유합니다.
초기화 과정에서 SQ와 CQ, 데이터 버퍼 풀을 fmap 시스템 호출과 MAP_SHARED로 양쪽 주소 공간에 매핑합니다. 이 구조는 I/O 데이터를 프로세스 사이에서 복사하지 않도록 합니다. 데이터 버퍼는 공유 메모리 풀에서 할당하며, 고정 크기 청크를 쓰는 방식과 B-tree 기반 redox-buffer-pool을 이용해 크기와 정렬에 맞춰 할당하는 방식을 지원합니다. 각 큐에는 생산자와 소비자가 하나씩 있어 공유 잠금 없이 인덱스를 관리합니다.
relibc에는 Linux liburing과 비슷한 redox-ring API를 추가했습니다. 애플리케이션은 redox_ring_queue_init_with_path()로 scheme 연결을 초기화하고, 공유 버퍼를 할당한 뒤 SQE(submission queue entry)에 작업 종류와 파일 인덱스, 버퍼 위치와 길이, 파일 오프셋을 기록합니다. redox_ring_submit()으로 여러 요청을 한꺼번에 제출하고 CQE(completion queue entry)를 받아 결과를 확인합니다. 이 API는 일반 프로세스 간 통신에도 쓸 수 있으며 RedoxFS와 NVMed 사이 통신에도 적용했습니다.
서비스와 드라이버 지원
RamFS와 NVMed에 링 버퍼 지원을 추가하고 테스트를 작성했습니다. scheme 쪽 작업자는 SQ에서 요청을 읽어 비동기 처리한 뒤 완료를 알립니다. 드라이버용 async executor도 구현했습니다. 현재는 코어 하나와 코어별 인터럽트 벡터 및 SQ/CQ 한 쌍을 쓰며, 다중 스레드 지원을 진행 중입니다. NVMe 드라이버는 executor를 사용하도록 바꿨고 virtio 등 다른 장치 지원은 향후 작업으로 언급했습니다. 세션을 종료하면 작업자를 멈추고 대기 중인 I/O를 취소하며 공유 자원을 정리합니다.
프로젝트 설명에 따르면 Redox Rings를 이용한 벤치마크는 동기식 시스템 호출 방식보다 14~15배 빠릅니다. 다만 이 수치는 해당 벤치마크의 비교 결과입니다. 실제 사용 환경의 작업 부하를 대표하는 수치인지는 글에서 확정하지 않았습니다.
커널과 IPC 최적화
팀은 링 버퍼만으로 줄이기 어려운 IPC 비용도 개선했습니다. 커널 리팩터링으로 중복 잠금과 해시맵 조회를 줄였고, IPC용 저비용 호출 경로를 추가했습니다. syscall로 커널에 들어온 호출자와 피호출자 사이에서는 XSAVE와 XRSTOR로 벡터 레지스터를 저장하고 복원하는 대신 레지스터를 초기화하는 빠른 전환 경로를 마련했습니다. 테스트한 AMD Ryzen 9 5950X에서는 두 명령의 비용이 합쳐 수백 사이클에 달했습니다.
kernel MR 694의 direct context switching은 스케줄러를 거치지 않고 준비된 scheme으로 바로 전환하도록 해 IPC 지연을 15~20% 줄였습니다. 또 가능한 경우 커널의 physmap을 2MB 페이지로 매핑합니다. acid heavy_forking 측정에서 L1 DTLB 미스율이 가장 높게 나타난 경우 75% 낮아졌습니다. 비 x86 플랫폼과 사용자 공간 페이지는 여전히 4KB 페이지를 씁니다.
IPC 왕복 지연은 약 5800사이클에서 2700사이클로 줄었습니다. 팀은 잠금과 syscall 진입 비용을 더 줄이고 IPC 기본 동작을 단순화하는 방안을 후속 작업으로 제시합니다. 현재 벤치마크는 지연의 대략적인 하한을 보여주는 수준이며, 링 버퍼 유무에 따른 현실적인 작업 부하의 비용 분포를 파악하려면 추가 조사가 필요하다고 밝혔습니다.
Reddit 반응
- @ribbon_45 — redox-os.org의 프로젝트 요약 링크를 공유했습니다.
- @servermeta_net — 정말 멋지네요!
- @RuddyEvacuation — NLnet 지원금이 유용하게 쓰여 기쁩니다. 링 버퍼는 커널 맥락에서 보기보다 까다로운 문제처럼 늘 느껴졌습니다. 제로카피만으로도 노력할 가치가 있습니다.
- @jorgesgk — 정말 잘했습니다!