UringMachine 파이버 스케줄러 구현은 여러 중요한 개선 사항을 포함합니다.
핵심 구성 요소 개선
-
뮤텍스 성능 최적화: UringMachine 뮤텍스가 Ruby 기본
Mutex보다 느렸던 문제를 해결했습니다. 불필요한futex_wake호출을num_waiters필드를 통해 대기 중인 파이버가 없을 경우 건너뛰도록 하여 성능을 크게 향상시켰습니다. -
메모리 관리 수정:
UM::Mutex및UM::Queue클래스에서RUBY_TYPED_EMBEDDABLE플래그를 제거했습니다. 이는 커널이futex변수를 대기하는 동안 해당 변수가 이동될 수 없도록 하여 안정성을 확보했습니다. -
I/O::Buffer 지원 강화: 모든 저수준 I/O API에
IO::Buffer지원을 추가하여, 파이버 스케줄러가IO::Buffer를 문자열로 변환할 필요 없이 UringMachine API를 직접 호출할 수 있게 되었습니다. -
예외 처리 개선: 잘못된 인자나 API 오용 시 발생하는
UM::Error와 RESP 오류 시UM::Stream::RESPError와 같은 사용자 정의 예외 클래스를 추가하여 오류 진단을 용이하게 했습니다.
Ruby 코어 통합 및 새로운 API
-
fork 후 스케줄러 동작 탐구:
fork후 파이버 스케줄러의 상태 재설정 필요성을 발견했으며, 이는io_uring인스턴스 공유 불가능 및 자식 프로세스의 파이버 손실 문제 때문입니다. -
**`Fiber::Scheduler
process_fork 훅 제안**: Samuel의 제안에 따라 fork 후 자동으로 호출되는 Fiber::Scheduler
process_fork` 훅 추가 PR을 제출했습니다. 이는 Ruby 4.0 릴리스에 병합될 가능성에 대한 기대를 모으고 있습니다.
- 프로세스 대기 API 추가: `UM
waitpid 대신 io_uring 버전의 waitid를 사용하는 UM
waitid 및 UM
waitid_status 두 가지 저수준 API를 새로 추가했습니다. waitid_status는 Process::Status` 객체를 반환합니다.
-
PID 관련 API:
UM.pidfd_open및UM.pidfd_send_signal을 추가하여 PID 관련 작업을 지원합니다. -
광범위한 테스트: 소켓 I/O, 파일 I/O, 뮤텍스, 큐, 스레드 대기 등
UM::FiberScheduler에 대한 포괄적인 테스트를 작성하여 Ruby가 파이버 스케줄러를 호출하는 방식에서 개선점을 발견했습니다.
Ruby I/O 레이어에 대한 통찰
-
파일 I/O와 소켓 I/O의 차이: Ruby가 일반 파일 I/O를 항상 블로킹으로 간주하여 별도 스레드에서 처리하는 반면, 소켓 I/O는 논블로킹으로 설정하고
io_wait훅을 사용한다는 점을 파악했습니다. -
io_uring의 잠재력:
io_uring이 모든 파일 디스크립터를 블로킹으로 처리하면서도 비동기 I/O를 수행할 수 있게 하여 기존 I/O 방식에 대한 많은 가정을 깨뜨린다는 점을 강조했습니다. 이는 Ruby I/O 구현을 단순화하고 성능을 극대화할 수 있는 기회를 제공합니다.