게임이나 엔진을 최적화할 때 가장 먼저 해야 할 일은 무엇일까요? 바로 무엇을 고쳐야 할지 정확히 아는 것입니다. 이때 등장하는 개념이 프로파일링(Profiling)입니다. 프로파일링은 프로그램이 느려지는 지점을 찾아내는 과정을 말합니다.
디버깅과 프로파일링의 차이점
흔히 디버깅과 비교해서 설명하곤 합니다. 디버깅이 프로그램의 오작동 원인을 찾는 것이라면 이쪽은 다릅니다. 프로파일링은 어디에서 시간이 가장 많이 소모되는지 밝혀내는 과정이죠. 이 차이는 생각보다 매우 중요합니다.

성능 문제는 우리 눈에 잘 보이지 않는 경우가 많습니다. 그래서 느낌이나 추측에 의존해 코드를 고치면 헛수고가 되기 쉽습니다. 이 부분이 복잡해 보이니까 느릴 것 같다는 판단은 위험합니다. 실제 병목과는 전혀 상관없을 수도 있기 때문입니다.
데이터에 기반한 최적화의 중요성
성능 최적화는 반드시 프로파일링 결과를 기반으로 이루어져야 합니다. 데이터를 보지 않고 진행하는 수정은 대개 성과가 없습니다. 오히려 코드를 더 복잡하게 만들 뿐이죠. 그렇다면 이 프로파일링은 어떤 방식으로 이루어질까요?
대부분의 프로파일러(Profiler)는 샘플링(Sampling) 방식으로 동작합니다. 샘플링이란 프로그램 실행 중 아주 짧은 간격으로 기록하는 것입니다. CPU가 지금 어디 코드를 실행 중인지 반복해서 확인하는 방법이죠.
샘플링 방식의 원리와 장점
예를 들어 1초에 수천 번씩 실행 위치를 찍어 둔다고 해보세요. 시간이 지나면 어떤 함수가 자주 등장하는지 통계가 쌓입니다. 이 통계를 보면 CPU 시간을 많이 쓰는 코드가 드러납니다. 자연스럽게 어디를 고쳐야 할지 알게 되죠.
샘플링 방식의 가장 큰 장점은 오버헤드(overhead)가 매우 적다는 점입니다. 프로파일러를 켜 놓아도 프로그램 동작이 크게 느려지지 않습니다. 그래서 실제 게임을 평소처럼 실행하며 성능을 관찰할 수 있습니다.
더 정밀한 측정이 필요할 때
다만 샘플링은 통계적 추정에 기반한다는 특징이 있습니다. 그래서 아주 짧게 실행되는 코드까지는 정확히 잡아내지 못할 수도 있죠. 미세한 타이밍 차이까지 보고 싶다면 다른 방식이 필요합니다. 이에 대비되는 방식이 계측(Instrumentation)입니다.
계측 방식은 함수가 시작될 때와 끝날 때 시간을 직접 기록합니다. 이 함수가 정확히 몇 밀리초를 사용했는지 측정하는 것이죠. 매우 정확한 데이터를 제공한다는 점이 큰 특징입니다. 하지만 그만큼 코드에 측정용 작업이 많이 들어갑니다.
상황에 맞는 도구를 선택하는 지혜
계측 방식은 실행 중에 부담이 커진다는 단점이 있습니다. 정확성은 높지만 시스템 부하도 큽니다. 그래서 실무에서는 두 방식을 상황에 따라 나누어 사용하곤 합니다. 전체적인 병목을 찾을 때는 샘플링을 먼저 씁니다.
샘플링으로 큰 그림을 본 뒤에 정말 중요한 구간을 찾습니다. 미세한 최적화가 필요한 경우에만 계측을 사용하는 식이죠. 중요한 것은 어떤 방식이든 객관적인 수치를 제공한다는 점입니다. 우리는 이 근거를 바탕으로 움직여야 합니다.
현명한 프로그래머의 최적화 전략
프로파일링의 목적은 무작정 열심히 최적화하는 것이 아닙니다. 가장 필요한 곳에만 노력을 집중하는 것입니다. 게임 엔진처럼 복잡한 시스템의 모든 코드를 빠르게 만들 수는 없습니다. 불가능에 가까운 일에 매달릴 필요는 없겠죠.
대신 진짜 병목을 찾아내고 그 부분에만 힘을 쓰는 것이 좋습니다. 이것이 가장 현명하고 효율적인 접근 방법이라 할 수 있습니다. 여러분도 이제 감이 아닌 데이터로 성능을 개선해 보세요.