황의권
서든어택2 프로그램팀 팀장
2007- Tibero(RDBMS)
2009.봄 - 가을 카바티나스토리
- 2011.여름 메이플스토리
- 2012.봄 아이러브커피 외
- 현재 서든어택2
발표자 소개
취미 : 코스츔 플레이어
4.
빌드 시간은 개발생산성에 밀접한 문제
- 특히 게임에선 개발 iteration 비용이 중요
누구나 얘기하지만 잘 챙기긴 어렵다
왜 빌드 발표요?
출처 : compiling (https://xkcd.com/303/)
5.
간단히 검색해 본NDC 관련 세션
• Unity Build로 빌드타임 반토막내기 – 송창규 [NDC10]
• 레가시 프로젝트의 빌드 자동화 – 최재훈 [NDC11]
• 효율적인 모바일 게임 개발을 위한 모바일 빌드 시스템과 모바일 배포 시스템 구축 노하우 –
윤보선/김태효 [NDC15]
• 하루에 3번! 삼시세끼 빌드 만들기! – 안현석 [NDC15]
빌드 엔지니어링은 단골 주제
6.
다양한 개발 환경은말할 것도 없고,
하나의 개발 환경에서도 수많은 상황을 고려해야 함
빌드 엔지니어링은 넓고 깊은 주제
7.
사례로 살펴보는
MSVC
빌드 최적화
팁
제목부연 설명
서든어택2 서버 개발 중 있었던 일
Microsoft Visual C++
빌드 생성 과정에 대한 엔지니어링
Rule of Thumb 중심 + 가벼운 연관지식
전체 개발 사이클의병목은 아니지만 commit이 망설여짐
상식 밖의 빌드 시간
• 당시 소스파일 크기(LOC) : 약 175K
• 데디케이티드 서버는 별도
심각성 분석 – 시간 문제
175K
도표 : 개발일정에 따른 LOC 변화
코드 정리
큰 마일스톤
14.
큰 용량이 기능과성능에 영향을 주지는 않았음
하지만 바이너리가 109메가면 이거 너무 심한 거 아니오
심각성 분석 – 용량 문제
15.
가설 1 :이런 이상 상황이 갑자기 발생한 특정한 시점이 있지 않을까?
진행 1 : 로그! 로그를 보자!
전략 선택 – 1단계
16.
이분검색을 해서 문제가되는 커밋을 찾자
- 총 서버 변경 리비전 수 : 약 3000
-> 이분검색 12(2^12=4096)번, 간단하네?
로그를 분석한다
17.
빌드 시간 검색
•CC.NET CI 빌드 로그
• 검색하기 너무 불편
• 검색툴을 만들까? -> 배보다 배꼽이…
• 직접 빌드해보면 되지 않을까?
• 12번 리비전이동/빌드
• 하지만 문제가 생긴 시점이 특정된다는 보장이 없다!
로그분석 – 시간 추적
18.
CI 빌드 바이너리는저장소에 커밋되지 않고 있었고orz
대신 서비스 서버 관리 툴이 쓰는 중간 저장소에 드문드문 로그가 있었다
- 최초 서비스 배포 버전(리비전 약 1000)이 이미 30MB
- 시간에 따라 거의 선형 증가하는 모습
로그분석 – 용량 추적
30MB
109MB
19.
과거 기록 분석은FAIL,
지금의 상황만 가지고 문제점을 찾아 돌파하는 정공법으로 전환
가설 2 : 바이너리 용량이 크게 나오는 게 빌드 시간에 영향을 주지 않을까?
진행 2 : 용량! 용량을 보자!
전략 선택 – 2단계
단순화한 MSVC 컴파일과정
전처리기
컴파일러
링커
전처리 지시자 처리(#include,#define, …)
모든 헤더파일이 풀린 큰 소스파일 생성
한 소스파일을 컴파일하여 obj 파일 생성
obj 파일과 lib 연결
exe/lib/dll 생성
22.
단순화한 SA2 게임서버빌드 과정
코어 lib 프로젝트
코어.lib
공통로직.lib
네트워크.lib
데이터베이스.lib
역할별 서버
프론트엔드서버.lib
매칭서버.lib
커뮤니티서버.lib
(그 외 로직 서버들)
단일 런처
서버런처.exe
23.
어떤 문제인지 명확히모르는 상태에서, 해결책 try
용량 관련한 빌드 옵션 체크 리스트
• 최적화 옵션 O1로?
• 디버깅 정보를 빼고 해볼까?
• 문자열 풀링이 안 되어 있다거나?
샷건 디버깅 – 용량 편
-> 효과는 0.1MB 미만
-> 위와 같음
-> 릴리즈 빌드에서는 강제 켜짐
실패
맵 파일 :빌드 때 옵션을 주면 생성되는 바이너리 구조 명세 TXT
영역별 시작 주소와 길이, 코드 영역의 각종 기호 포함
맵 파일 분석
Start Length Name Class
0001:00000000
0001:00025f30
…
0002:00000000
0002:00000b40
…
0002:000078e0
0002:063c7bf0
0003:00000000
…
00025f2cH
002ccb00H
00000b40H
00000008H
0637bf20H
00088b70H
000029b8H
.text$di
.text$mn
.idata$5
.CRT$XCA
.rdata
.xdata
.data
CODE
CODE
DATA
DATA
DATA
DATA
DATA
수상하다!
.rdata : (주로) 전역 상수,
문자열같은 것이 위치
26.
DUMPBIN : MSVC내장 툴
실행파일/라이브러리 구조를 조금 더 면밀히 보고 싶을 때 사용
File Type: EXECUTABLE IMAGE
Summary
2606000 .data
28000 .pdata
6455000 .rdata
9000 .reloc
1000 .rsrc
31D000 .text
1000 .tls
DUMPBIN 활용 – 기본 정보
0x6455000
= 105205760
(100MB)
27.
DUMPBIN /section:.rdata
File Type:EXECUTABLE IMAGE
SECTION HEADER #2
.rdata name
6454BFA virtual size
31E000 virtual address (000000014031E000 to 0000000146772BF9)
6454C00 size of raw data
31C800 file pointer to raw data (0031C800 to 067713FF)
…
-> 문제가 맞아 보임, 하지만 아직 정보가 부족
DUMPBIN 활용 – 섹션 상세 정보
C++ 코딩 관련기본 상식을 잘 지키는지 체크
• 헤더, 특히 시스템 헤더 include를 최소화
• 모듈 의존성을 단순하게
• 헤더와 몸통(cpp) 엄격한 분리 등
빌드 옵션 조절
• 디버깅 레벨 조절
샷건 디버깅 – 시간 편
35.
• PCH(Pre-Compiled Header)사용 중
• 헤더와 몸통의 분리
• 손으로 짠 모듈에서는 엄격히 지키는 편
• Pimpl idiom도 일부 선택 활용 중
• 자동 생성 코드에서 소홀한 점 추가 발견
• 시스템 / 외부 헤더 파일 관리
• 템플릿 전방선언을 끼얹을 요소 발견
• (헤더에서 boost 타입 참조하는 일부 경우)
우리 프로젝트 체크리스트
36.
자주 포함되는 코어헤더들의 시스템 헤더 include를 정리하고
자동생성된 코드에도 규칙을 엄격히 적용한 결과
PacketAll.h(모든 패킷 헤더를 다 뭉쳐본 파일)의 전처리 끝난 LOC 변화
183,620 줄 -> 5,278 줄
줄어든 시간 :
• 10초 내외로 거의 변화 없음 orz
• 그 외 디버깅 레벨 등 옵션 조절도 모두 미미한 영향
코드 정리 결과
봐야 할 기호의수가 너무 많은 경우
• 네임스페이스를 열어버린 경우(예 : 헤더에서 using namespace std;)
헤더파일 의존성이 복잡한 경우
• 컴파일 타임에 드러나지 않고 링크 타임에 드러난다거나?
• 이번에도 자동 생성 파일이 문제인가?
분산 컴파일은 되는데 왜 분산 링크는 없나?
• 분산된 걸 모으는 게 링크인데 링크를 또 분산하면 분산된 링크를 모으는 링크가..
브레인스토밍 : 링크 시간에 관하여
40.
여기서 떠오른 팀원과의대화
Q: 근데 빌드하는 데 15분이면 로컬 작업도 힘들잖아요?
A: 아뇨 로컬에선 디버그 빌드로..
디버그 빌드는 : 2분 30초
..아 이 이야기를 분명 처음에 들었는데
잠깐!
들인 시간
• 업무시간(관여한모든 사람의) 8시간 남짓
한 일
• 시행착오(샷건 디버깅), 야크쉐이빙(코드정리)에 시간 허비
• Map 파일 분석과 DUMPBIN을 써서 용량문제 발견
• 자동생성코드 위치이동으로 해결
• LTCG 옵션 꺼서(…) CI빌드 시간 단축
회고
50.
소위 삽질이 많았다
-샷건 디버깅은 핵심 문제에 접근하는 데에는 비효율적
- 귀찮아도 문제를 분석하고 접근하는 버릇을 들이자!
- 실무에서 멀어졌던 팀장이 일 잡았을 때의 폐해
교훈
51.
링크 타임 코드생성의 단위 비용을 줄일 순 없을까?
- 다단계 링크 구조를 개선해보면?
- Unity Build를 쓰면 더 빠를 것 같은 예감?
- 마지막엔 lib들끼리 링크하는데 소용 없을지도..
Future work