클라가 느리면 서버도 느려진다
이 영상에 나오는 용어 15개.
- 공유 브로드캐스트 버퍼
- 같은 패킷을 여러 세션에 보낼 때 복사 대신 함께 참조하는 버퍼다. 참조하는 세션이 모두 보내야 해제되므로 느린 세션 하나가 메모리를 붙잡는다.
- 논블로킹 send
- 버퍼가 차도 기다리지 않고 바로 반환하는 전송 방식이다. 로직 스레드가 느린 클라이언트 때문에 멈추지 않게 해 준다.
- 메인 스레드
- 클라이언트의 게임 로직과 렌더를 돌리는 스레드다. 프레임마다 수신 큐에서 정해진 개수만큼 패킷을 꺼내 처리한다.
- 백프레셔 (backpressure)
- 받는 쪽이 느릴 때 그 압력이 보내는 쪽으로 거슬러 전달되는 현상이다. 이 영상에서는 클라이언트 수신 큐에서 시작해 서버 앱 송신 큐까지 전달된다.
- 수신 스레드
- 클라이언트에서 소켓 읽기만 전담하는 스레드다. 렌더가 느려도 커널 수신 버퍼를 계속 비워 서버 쪽으로 압력이 가지 않게 한다.
- 수신 큐
- 수신 스레드가 받은 패킷을 메인 스레드가 꺼내 갈 때까지 담아 두는 앱 메모리 안의 큐다.
- 앱 송신 큐 (세션 송신 큐)
- 서버가 세션별로 두는, 커널에 아직 넘기지 못한 데이터의 대기열이다. 느린 클라이언트일수록 커지고, 상한에 닿으면 연결을 끊는 경우가 많다.
- 프레임당 처리 예산
- 한 프레임에 처리할 패킷 수의 한도다. 프레임 시간이 길어지는 것을 막는 대신 남은 패킷은 다음 프레임으로 넘어간다.
- EAGAIN
- 논블로킹 소켓에서 커널 송신 버퍼가 가득 차
send()가 지금은 쓸 수 없다고 돌려주는 오류 코드다. 앱은 데이터를 자기 큐에 두고 나중에 다시 보내야 한다. - FPS
- 초당 프레임 수다. 메인 스레드가 프레임마다 패킷을 꺼내므로 FPS가 떨어지면 초당 처리량도 같이 떨어진다.
- GC 정지
- 가비지 컬렉터가 메모리를 정리하는 동안 스레드가 멈추는 현상이다. 수신 경로에서 할당이 많으면 자주 일어난다.
- IOCP
- Windows의 비동기 I/O 완료 통지 방식이다. 전송 요청을 걸어 두면 대기 중인 바이트가 쌓이므로 여기에도 상한이 필요하다.
- Send-Q
ss출력에서 연결별로 커널 송신 버퍼에 남아 상대의 ACK를 기다리는 바이트 수다. 특정 연결만 크면 그 클라이언트가 느리게 받아가고 있다는 신호다.- SO_RCVBUF / SO_SNDBUF
- 소켓의 커널 수신 버퍼와 송신 버퍼 크기 옵션이다. 앱이 읽지 않으면 수신 버퍼가, 상대가 받지 않으면 송신 버퍼가 찬다.
- Zero Window
- TCP 수신 측이 ACK에 수신 윈도우 0을 알려 더 받을 수 없다고 알리는 상태다. 송신 측 커널은 윈도우가 다시 열릴 때까지 전송을 멈춘다.