Firefox의 Rust 기반 고속 UDP I/O

1 month ago 11

  • Firefox의 HTTP 트래픽 약 20%가 HTTP/3을 사용하며, 이는 QUIC 및 UDP 위에서 작동함
  • 기존 네트워크 I/O 계층인 NSPRRust 기반 quinn-udp로 대체하면서 성능과 메모리 안전성을 강화함
  • 각 운영체제별로 최신 시스템 콜(multi-message, segmentation offloading 등)을 적극적으로 활용해 성능 최적화를 적용함
  • WindowsMacOS에서는 일부 기능이 호환성, 드라이버 이슈 등으로 제한되었으나, Linux에서는 최적 성능을 확인함
  • QUIC ECN 지원과 UDP I/O 관련 다양한 플랫폼별 시행착오, 버그 해결 경험이 향후 프로젝트 및 오픈소스 생태계에도 도움이 될 전망임

동기

  • Firefox HTTP 트래픽의 약 20%가 HTTP/3을 사용하며, 이는 QUIC을 통해 동작하고, 다시 UDP 위에서 구현됨
  • Firefox는 역사적으로 NSPR 라이브러리를 네트워크 I/O에 사용했으나, UDP I/O 관련 기능이 오래되고 제한적임 (주요 함수는 PR_SendTo, PR_RecvFrom)
  • 운영체제들은 최근에 멀티 메시지 시스템 콜(ex. sendmmsg, recvmmsg)과 세그멘테이션 오프로드(GSO, GRO) 같은 네트워크 최적화를 제공함
  • 이러한 기술들은 UDP I/O 성능을 크게 향상시킬 수 있음
  • Firefox가 기존 UDP I/O 스택을 현대적 시스템 콜로 교체해 이점을 얻을 수 있는지 모색함

개요

  • 프로젝트는 2024년 중반 시작, 목표는 Firefox의 QUIC UDP I/O 스택을 모든 지원 OS에서 현대적 시스템 콜로 재구축하는 것임
  • 성능 개선과 더불어, UDP I/O에 메모리 안전성이 보장되는 Rust를 활용해 보안성 향상도 도모함
  • QUIC 자체는 이미 Rust로 구현되어 있어서, Rust 기반 quinn-udp 라이브러리 위에서 개발을 진행함
  • OS 간 시스템 콜 차이는 개발 난이도를 높였으나, quinn-udp 덕분에 개발 속도가 크게 개선됨
  • 2025년 중반 현재, 대다수 Firefox 사용자에게 적용이 진행 중이며, 성능 벤치마크에서 최대 4Gbit/s로 대폭 상승하는 결과를 보임

UDP I/O 구조와 현대적 최적화 방식

단일 데이터그램 전송

  • 기존 방식은 sendto와 recvfrom을 사용, 한 번에 단일 UDP 데이터그램만 송수신
  • 사용자 공간과 커널 공간 간의 전환 비용은 데이터그램 단위로 지불되어, 대용량 트래픽 환경에서는 비효율적임
  • 예시: 1500바이트 미만의 패킷을 초당 수백 Mbit 이상으로 보내려면 상당한 오버헤드 발생

다중 데이터그램 배치 전송

  • Linux 등 일부 OS에서 sendmmsg 및 recvmmsg와 같은 멀티 메시지 시스템 콜 지원
  • 여러 데이터그램을 한 번에 송수신 하여, 오버헤드를 대폭 줄일 수 있음

단일 대용량 세그먼티드 데이터그램

  • GSO(송신) , GRO(수신) 등 오프로드 기술로 큰 UDP 데이터그램을 OS 또는 NIC에서 자동으로 분할해 전송
  • 네트워크 인터페이스가 패킷 단위로 분리, 체크섬 계산 및 헤더 붙이기를 처리
  • 이를 통해 애플리케이션 단은 단 한 번의 시스템 콜만으로 다수의 실제 패킷 처리 가능
  • GSO 활성화 상태에서는 Wireshark 등 일부 네트워크 툴의 패킷 분석 지원이 미흡

Firefox의 NSPR 대체 과정

  • 우선 단일 데이터그램 송수신 구조에서 quinn-udp로 NSPR를 대체
  • QUIC 구현체의 데이터그램 처리 파이프라인을 배치 송수신 및 세그먼테이션을 지원하도록 리팩터링
  • multi-message 콜, segmentation offload 콜 모두 상황에 맞게 활용
  • 플랫폼별 예외 처리 및 다양한 I/O 개선 기능이 추가됨

플랫폼별 세부 사항

Windows

  • Windows는 WSASendMsg/WSARecvMsg를 제공, 전통적인 MTU 사이즈 데이터그램 또는 대형 세그먼티드 데이터그램 지원
  • Linux의 GSO/GRO에 대응하는 Windows의 USO(송신) / URO(수신)
  • 초기에는 단일 데이터그램 콜만 사용하여 문제 없었으나, URO 활성화 시 특정 환경(예: Windows on ARM + WSL)에서 QUIC 패킷 길이 판별 불가로 인해 페이지 로딩 실패 버그 발생
  • USO/송신도 사용했으나, Firefox Windows 설치 환경에서 패킷 손실 증가 및 네트워크 드라이버 크래시 등 부작용 발견
  • 현재 Firefox에서는 URO/USO 비활성화 상태 유지 및 추가 디버깅 진행 중

MacOS

  • MacOS에서는 기존 sendto/recvfrom 대신 sendmsg/recvmsg로 quinn-udp 도입
  • 세그멘테이션 오프로드 기능은 활성화되어 있지 않음
  • 대신 공식 문서화되지 않은 sendmsg_x/recvmsg_x로 배치 전송 지원, quinn-udp에 비공식적으로 적용
  • 애플이 향후 해당 호출을 제거할 수 있음에 따라, 기본 활성화 없이 테스트만 진행 후 실제 릴리즈에는 미포함

Linux

  • sendmmsg/recvmmsgGSO/GRO 모두 지원, quinn-udp는 송신 시 GSO를 기본 우선시함
  • Firefox는 연결마다 UDP 소켓을 별도로 사용해 프라이버시 강화를 도모(4-tuple 구분)
  • 이 구조에서는 세그멘테이션 오프로드의 이점이 극대화, sendmmsg/recvmmsg의 교차 전송 이점은 제한적
  • 네트워크 샌드박스, 런타임 GSO 지원 체크 등 소규모 변경 외 어려움 없이 도입 성공

Android

  • Android는 Linux와 달리 시스템 콜 처리 경로 및 보안 필터(예: seccomp)가 다름
  • x86 기반 Android 5 등 매우 오래된 플랫폼의 지원 및, socketcall 우회, 오류 처리 등 다양한 호환성 이슈 존재
  • 일부 환경에서는 ECN 비트가 활성화된 송신 호출 시 오류(EINVAL) 발생, quinn-udp에서 재시도 및 옵션 해제 전략 적용
  • Quinn 커뮤니티에서의 다양한 개선 이점 덕분에 Firefox도 자동으로 개선 효과를 누릴 수 있음

ECN(명시적 혼잡 알림) 지원

  • 최신 시스템 콜 도입 덕분에 ancillary data(부가 데이터) 송수신 지원, QUIC ECN 지원 가능
  • 소규모 버그는 있었으나, Firefox Nightly에서 절반 이상의 QUIC 연결이 ECN outbound 경로로 동작
  • L4S 등 신기술이 부각됨에 따라 ECN 지원의 중요도와 활용성 상승

결론 요약

  • Firefox의 QUIC UDP I/O 계층을 quinn-udp 기반 Rust 구현체로 교체, 성능과 보안성을 동시에 확보
  • dated 시스템 콜 대신 각 OS별 최신 I/O 시스템 콜을 활용하여 처리량 향상 및 ECN 지원이 가능해짐
  • Windows 등 일부 최적화 기능은 호환성 이슈로 추가 개선 필요
  • QUIC 사용률이 지속적으로 늘어남에 따라, 앞으로도 OS/드라이버 수준의 지원이 계속 발전할 것임

Read Entire Article