피드로 돌아가기
The Day the Language Became the Bottleneck
Dev.toDev.to
Backend

Rust 전환으로 1M 연결 시 p99 지연시간 50ms에서 14.2ms로 단축

The Day the Language Became the Bottleneck

pretty ncube2026년 5월 27일3advanced

Context

Go 1.20 기반 Treasure Hunt Engine이 500k 동시 접속 시 GC Pause 급증으로 인한 SLO 달성 실패 상황. mcache_get 오버헤드와 런타임 Escape Analysis로 인해 트래픽 증가에 따른 성능 저하가 지수적으로 상승하는 언어적 한계 직면.

Technical Solution

  • Go의 GC 오버헤드 제거를 위해 Rust 1.75.0 및 tokio 1.28 기반의 Core Event Loop 재설계
  • 64-byte 플레이어 상태 구조체의 메모리 단편화 12% 감소를 위해 mimalloc 글로벌 할당자 채택
  • 파워업 발생 시 쓰기 경합 32% 해결을 위해 Arc에서 Arctokio::sync::RwLock으로 동시성 제어 모델 변경
  • gogoproto를 Prost로 교체하여 Zero-copy 파싱을 통한 직렬화 오버헤드 제거
  • Borrow Checker의 엄격한 제약을 통해 런타임 메모리 안정성 확보 및 RSS 메모리 사용량 최적화

Impact

  • p99 Latency: 50ms $\rightarrow$ 14.2ms (1M connections 기준)
  • Allocation Rate: 42MB/s $\rightarrow$ 8MB/s
  • CPU Usage: Peak 시 82% $\rightarrow$ 47%로 감소하여 2 vCPUs 여유 자원 확보
  • Memory Usage: 3.4GB $\rightarrow$ 1.8GB RSS로 최적화
  • GC Pause: 완전히 제거되어 Scheduler Latency 0.4ms $\pm$ 0.1ms 달성

Key Takeaway

특정 트래픽 임계점(Inflection Point)에서 런타임의 추상화 비용이 시스템 전체의 병목이 될 때, 메모리 모델을 직접 제어할 수 있는 언어로의 전환이 유일한 해결책이 될 수 있음.


1. GC 기반 언어에서 Tail Latency 급증 시, 단순 튜닝 전 할당자(Allocator) 프로파일링 수행

2. 고빈도 쓰기 경합이 발생하는 공유 상태는 Mutex보다 RwLock 적용 검토

3. 언어 런타임 변경과 같은 고위험 작업 시 전체 교체가 아닌 단일 마이크로서비스 단위의 Canary 배포 전략 수립

4. Zero-copy 라이브러리 도입을 통한 직렬화/역직렬화 비용 최적화 검토

원문 읽기