1:21 · threads · tick loop · message queue · AOI

서버 안의 50ms, 무슨 일이 일어날까?

이 영상에 나오는 용어 14개.

락 경합
여러 스레드가 같은 공용 자원의 락을 잡으려고 기다리는 상황이다. 경매장, 길드처럼 존 사이에 공유되는 데이터에서 생긴다.
로직 스레드
존 하나의 게임 상태를 처리하는 스레드로 존당 1개다. 한 스레드만 상태를 바꾸므로 존 내부에는 락이 없다.
메시지 큐
I/O 스레드가 해석한 요청을 로직 스레드가 꺼내 가기 전까지 쌓아 두는 대기열이다. 깊이를 처리량으로 나누면 대기 시간이 나온다.
브로드캐스트
한 플레이어의 상태 변화를 AOI 안의 다른 플레이어들에게 전송하는 일이다. 인원이 N명이면 갱신(메시지)이 틱당 N × (N − 1)개까지 늘어난다.
송신 큐
클라이언트로 보낼 패킷이 실제 전송 전에 대기하는 버퍼다. 느린 클라이언트의 송신 큐가 차면 메모리가 늘고 연결이 끊긴다.
존 (Zone)
서버가 월드를 나눠 관리하는 단위다. 존마다 메시지 큐와 로직 스레드가 하나씩 붙는다.
죽음의 나선
처리가 늦어져 일이 더 쌓이고, 쌓인 일 때문에 처리가 더 늦어지는 악순환이다. 유입이 처리량을 넘는 상태가 이어질 때 생기고, 방치하면 서버 다운으로 이어진다.
틱 (Tick)
서버가 게임 월드를 한 번 갱신하는 주기다. 이 영상에서는 50ms마다 메시지 처리부터 브로드캐스트까지 한 바퀴를 돈다.
틱 예산
틱 하나에 허용된 시간이다. 처리 시간이 예산을 넘으면 다음 틱이 늦게 시작한다.
틱레이트
초당 틱 횟수로 Hz 단위로 쓴다. 20Hz면 틱당 50ms 예산이고, 틱이 길어지면 실제 Hz가 떨어진다.
AOI (Area of Interest)
각 플레이어가 보는 범위, 즉 시야다. 서버는 이 범위 안의 플레이어에게만 변경 사항을 보낸다.
GC Stop-the-world
가비지 컬렉터가 메모리를 정리하는 동안 프로세스의 스레드를 멈추는 구간이다. C#·Java 같은 GC 언어에서는 같은 프로세스의 모든 존 틱이 같이 멈춘다.
I/O 스레드
소켓 수신·송신, 암호화와 복호화, 직렬화를 맡는 스레드다. 게임 로직은 돌리지 않는다.
p99
측정값을 정렬했을 때 상위 1% 경계 값이다. 틱 p99는 가끔 튀는 느린 틱을 잡아낸다.