피드로 돌아가기
When Your Search Tree Becomes the Bottleneck in a Distributed Game Server
Dev.toDev.to
Backend

Rust 기반 R-tree 도입으로 검색 지연시간 20배 단축 및 Tick Jitter 제거

When Your Search Tree Becomes the Bottleneck in a Distributed Game Server

pretty ncube2026년 5월 27일3advanced

Context

LuaJIT 기반의 평면 테이블 구조로 인한 O(n) 검색 복잡도와 과도한 Hash Lookup 발생. 120명 동시 접속 시 검색 지연시간이 28-42ms까지 상승하며 60 TPS 유지 조건인 16ms를 초과한 상황.

Technical Solution

  • Rust 기반 별도 프로세스로 Indexer를 분리하여 LuaJIT GC 영향권에서 완전히 탈피
  • O(log n) 쿼리 성능을 보장하는 rstar crate의 R-tree를 통한 공간 인덱싱 구현
  • FlatBuffers를 활용한 직렬화 경계 설계를 통해 프로세스 간 데이터 전송 오버헤드 최소화
  • Rust Borrow Checker 도입으로 Lua C 모듈에서 발생하던 메모리 Segfault 문제 근본적 해결
  • Heap 메모리 관리 최적화를 위해 jemalloc arena 튜닝을 통한 99th percentile 지연시간 단축

Impact

  • 검색 요청 지연시간: 28-42ms → 1.8-3.9ms로 약 20배 개선
  • LuaJIT 메인 루프 지연시간: 95th percentile 기준 12.1ms → 3.8ms로 감소
  • GC Pause: 최대 5.8ms에서 1.2ms로 획기적 감소
  • Indexer 리소스 사용량: RSS 48MB 수준의 안정적인 메모리 점유율 유지

Key Takeaway

언어의 실행 속도보다 데이터 구조의 시간 복잡도와 런타임의 GC 동작 특성이 성능 병목의 핵심 원인임. 특히 실시간성이 중요한 시스템에서는 핵심 연산부를 GC가 없는 언어로 분리하고 데이터 직렬화 비용을 지불하더라도 예측 가능한 성능(Predictability)을 확보하는 설계가 유효함.


1. CPU Profiling 시 단순 언어 속도가 아닌 Hash Lookup 및 GC Pause 비율을 먼저 분석할 것

2. 공간 쿼리 최적화 시 Flat Table 대신 R-tree 또는 Quadtree 같은 공간 인덱스 구조 검토

3. 고성능 모듈 분리 시 FlatBuffers와 같은 Zero-copy 직렬화 도구로 통신 비용 최적화

4. 정적 데이터셋의 경우 R*-tree보다 빌드 속도가 빠른 Packed Hilbert R-tree 적용 고려

원문 읽기