더북(TheBook)

1.16.4 디바이스 타임이 섞인 잠금

디바이스 타임(1.9절 참고)이 있을 때는 다른 스레드가 자주 접근하는 리소스에 대한 잠금을 하지 말아야 하는데도, 우리는 알게 모르게 디바이스 타임이 섞인 잠금을 하는 실수를 하고는 합니다. 그중 특히 자주 하는 실수는 로그 출력이나 콘솔 출력입니다.

우리에게 매우 익숙한 콘솔 출력 함수(printfcout)는 사실 운영체제 안에서 꽤 무거운 일을 합니다. MS-DOS 기준에서 커맨드라인 출력은 MS-DOS에서 제공하는 인터럽트나 BIOS 인터럽트의 형태로 이루어집니다. 통상적인 게임 로직 연산 처리보다 훨씬 많은 시간을 차지하지요. 윈도 기준에서 커맨드라인 출력은 그래픽 모드 화면에서 콘솔 창처럼 생겼으나, 실제로는 그래픽 모드 화면에서의 그래픽 폰트 렌더링입니다. 이 과정에서 운영체제가 하는 연산량은 게임 로직 연산 처리를 훨씬 상회합니다.

물론 콘솔 출력이나 로그 출력이 디스크나 네트워크 I/O의 디바이스 타임만큼 긴 시간(보통 수백 마이크로초)은 아니지만, 콘솔 출력은 게임 서버에서 통상적인 연산 처리보다는 훨씬 많은 시간을 차지합니다.

게임 서버를 개발할 때 디버깅 목적으로 많은 콘솔 출력을 뿌릴 때기 있는데, 이때 게임 서버의 메모리 영역에 잠금을 하는 사람이 많을 것입니다. 그런데 이 과정에서 서버 처리를 할 때 병목 현상이 발생합니다.

void func()
{
  lock(mutex);
 
  a...;
  b...;
 
  cout << a << b; // 콘솔 출력
}

동시접속자는 많은데 게임 서버에서 CPU 사용량이 적게 나오는 경우, 이 때문에 문제가 난다고 보면 될 것 같습니다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.