Precompiled header를 씁시다 (제발)

윈도우 프로그래머라면 precompiled header가 익숙할 것이다. stdafx.h 바로 그 녀석이다. C/C++ 컴파일러의 컴파일 단위는 무조건 .c/.cpp 하나씩이다 (여담으로 그래서 파일간, 즉 .obj 파일들 넘어서 최적화 하는 것이 쉽지 않다). 그래서 개개의 .c/.cpp 파일을 컴파일할 때 #include를 하는 모든 헤더를 당연히 매번 파싱 해야한다. 간단한 프로그램은 괜찮은데, windows.h 와 같이 덩치가 무지 큰 헤더 파일을 #include하는 모든 파일을 매번 컴파일하면 시간이 상당히 걸린다. Precompiled header는 이런 비용을 줄이기 위해 나온 것으로 특정 헤더 파일을 미리 파싱한 결과물을 .pch 파일로 덤프시킨다. 그리고 다른 파일들은 이 .pch를 단순히 사용함으로써 중복된 파싱 작업을 없앨 수 있다.

VC++는 디폴트로 이 precompiled header를 사용한다. Precompiled header가 작동하는 원리는 다음과 같다.

  1. 덩치가 크거나 거의 바뀌지 않는 정의 같은 것을 모두 stdafx.h에 넣는다.
  2. stdafx.cpp는 /Yc "stdafx.h" 옵션을 줘서 컴파일 한다. (Create)
  3. 다른 .cpp 파일들은 /Yu "stdafx.h" 옵션을 준다. (Use)

실제로 windows.h 같은 것을 사용하는 프로젝트에서 PCH를 쓰냐 안 쓰느냐는 컴파일 속도에 지대한 영향을 미친다. 하나 오해하지 말아야할 것은 precompiled header의 이름은 꼭 stdafx.h/cpp일 필요가 없다. 아무런 파일 이름도 된다.

그런데 리눅스 gcc도 precompiled header라는 것이 있다. 여기를 보면 분명히 지원을 한다. 직접 테스트는 해보지 않았지만 확장자를 .gch로 하면 gcc가 알아서 만들어 주는 것 같다. 그런데 지금까지 리눅스 프로젝트에서 PCH를 쓰는 경우를 거의 보지 못했다. 컴파일 시간을 매우 단축시킬 수 있는데 사람들이 몰라서 안 쓰는 것일까 아니면 컴파일 하는 동안 커피 한 잔의 여유라도 가지려고 안 쓰는 것일까? 당연히 인텔 C/C++ 컴파일러도 PCH를 지원한다.

 

실제로 PCH의 위력은 대단하다. 요즘 FTP 클라이언트인 FileZilla 3.0 소스를 받아서 좀 고칠 것이 있어서 삽질을 좀 했다. 100여개의 cpp 파일이 있는 작지 않은 규모이다. 컴파일 되는 모습을 보니 파일 하나당 1~2초씩 걸리는 것을 볼 수 있었다. 역시나 PCH를 사용하고 있지 않았다. 그래서 테스트를 좀 해봤다. 다행히 대부분의 모든 파일질라 소스들이 FileZilla.h라는 파일을 공통적으로 #include 하고 있었다. 그래서 이 파일을 PCH로 만들었다. 그랬더니 그 결과는?

파일질라 3.0 클라이언트에는 engine과 interface 두 프로젝트가 있는데 PCH가 없을 때는 50초와 55초의 컴파일 시간이 걸렸다. 그런데 PCH를 사용한 뒤에는 각각 16초와 27초로 거의 절반 이상의 시간이 절약됨을 볼 수 있었다. (사실 파일질라 클라이언트 소스는 윈도우용이라도 VC++에서 완벽히 링크까지 되지 않는다. 그래서 MinGW 깔고 캐삽질이 필요하다. 위의 시간은 대략 링킹을 제외한 대충 컴파일 되는데까지 측정한 시간이다.)

 

이런 비효율은 다른 곳에서도 쉽게 찾아볼 수 있다. 요즘 연구하는데 주로 들여다보는 벤치마크 프로그램 중 ITK 라는 것이 있다. 의료영상에 관련된 소프트웨어 툴킷이다. 이게 좀 무식하게 덩치가커서 툴킷과 Apps를 다 컴파일하면 하드 한 10기가를 차지 한다. 그 뿐만 아니라 컴파일을 다 하는데 40~50분은 족히 걸린다. 8코어 서버 머신에서 돌리면 그나마 빠르지만 듀얼 코어 정도에서 돌리면 세월아 네월아다.

그런데 역시 컴파일 되는 꼬라지를 보고 있으면 욕이 튀어나온다. 예를 들어, 의료영상 이미지 프로세싱 중에 Registration이라는 알고리즘이 있다. 이 알고리즘을 여러가지로 구현한 테스트 프로그램들이 ImageRegistration1, ImageRegistration2 이런식으로 15번까지 있다고 하자. 웃기게도 저 프로그램 자체는 모두 달랑 200줄도 안 되는 .cpp 파일 하나 씩으로 구성되어있다. 대부분은 공통적인 모듈을 그대로 사용한다. 그래서 같은 파일들이 죽으라고 계속 반복적으로 컴파일 된다. (더 최악인 건 최적화 옵션을 빡세게 주면 반복적인 동일한 최적화를 계속 한다는 것)

물론 이건 PCH를 쓴다고 다 해결되는 문제는 아니다. 분명 SharedLib을 씀에도 저런 불필요한 컴파일 작업이 반복되는 것은 다른 멍청함 때문일 것이다. 그러나 수 많은 헤더파일을 적어도 PCH로 만들면 분명히 컴파일 시간은 매우 단축될 것이다.

 

C/C++의 문제점 중 하나가 지저분한 헤더파일로 인한 얽히고 섥힌 의존관계로 길어지는 컴파일 시간일 것이다. 혹시 프로젝트 빌드 시간이 지나치게 길다면 한 번 중복되는 헤더파일들이 반복적으로 파싱이 되고 있지 않은지 살펴보고 이들을 다 PCH로 만들면 좋을 것이다. PCH를 쓰지 않는 덩치큰 프로젝트들을 규탄하는 바이다!! 오늘 하루 종일 컴파일 하다가 홀라당…

p.s. 참고로 VC++에서 특정 소스파일이 물고 있는 헤더파일 목록은 GUI 프로퍼티 페이지에서도 고칠 수 있고 (C/C++ – Advance – Show Includes) 혹은 /showIncludes 옵션으로도 볼 수 있다.

참고: GNU gcc에서 PCH 사용하기

사실 빌드 속도를 가장 높이기 쉬운 방법 중 하나는 IncrediBuild와 같은 툴을 이용하는 방법도 있다. 예전 회사에서 느린 빌드 속도에 답답할 때, 파일 하나씩을 회사의 모든 컴퓨터로 뿌린 다음에 컴파일해서 취합하면 정말 좋겠다라는 생각을 했었는데, 그 아이디어가 구현된 것이 IncrediBuild...

by object | 2008/06/30 14:03 | 컴퓨터 | 트랙백(2) | 핑백(2) | 덧글(12)
트랙백 주소 : http://minjang.egloos.com/tb/1956289
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from hyoseung at 2008/07/01 09:13

제목 : Compiler cache
회사에서 요즘 하는 프로젝트가, 컴파일 타임이 무쟈게 오래 걸린다; 별로 하는것도 없는 S/W의 컴파일 타임이 오래 걸리는 주된 원인은... 네트워크 미들웨어가 자동 생성해주는 어마어마한 분량의 소스코드 때문 -_-; 얘 혼자 뱉어내는 텍스트가 10메가쯤 되는거 같은데... 그 중 자주 사용되는 헤더 크기가 1.5메가쯤;; 전체 프로젝트에서 대략 200개가 넘는 오브젝트들이 저 헤더를 인클루드 하는데, 한번 리빌드를 하면 후덜덜하다. 타겟 머신......more

Tracked from eslife's me2.. at 2008/07/01 09:54

제목 : 사진찍는프로그래머의 생각
Precompiled header를 씁시다 (제발) stdafx.h 에 이것저것 넣다 보면 너무 지저분하다는 이유로 직접 사용하는 헤더에 옮겨놓곤 했는데, 컴파일 시간 절약을 위해서는 가능한 stdafx.h 로 다시 몰아야겠다....more

Linked at 코딩 공작소 : [펌] Pre.. at 2008/07/07 17:51

... 씩을 회사의 모든 컴퓨터로 뿌린 다음에 컴파일해서 취합하면 정말 좋겠다라는 생각을 했었는데, 그 아이디어가 구현된 것이 IncrediBuild...스크랩: http://minjang.egloos.com/1956289 ... more

Linked at Mono log : gcc p.. at 2008/08/18 17:17

... Precompiled header를 씁시다 (제발) gcc 3.4 부터 있는 precompiled header 사용방법 Using Precompiled Headers 좋은 동기 부여가 된 글입니다 ... more

Commented by xeraph at 2008/06/30 14:34
아 gcc도 되는 것이었군요 (..);;
Commented by Gerald at 2008/06/30 14:49
PCH 개념을 제대로 알고 가네요 ^^ 감사...
Commented by 우왕ㅋ굳ㅋ at 2008/06/30 15:18
=> 참고로 VC++에서 특정 소스파일이 물고 있는 헤더파일 목록은 GUI 프로퍼티 페이지에서도 고칠 수 있고

요건 어디에 있나요? 못찾겠네요
Commented by object at 2008/06/30 15:28
프로젝트 프로퍼티 (Alt+F7) 를 누르면 나옵니다. (C/C++ – Advance – Show Includes) 찾으실 수 있을 겁니다.
Commented by 최재훈 at 2008/06/30 17:59
PCH가 없으면 곤란하긴 하지만, 이게 또 설계상의 문제점을 감추는 데 주로 악용되기 때문에, 심경이 복잡하지요.
Commented by object at 2008/07/01 01:27
설계상의 문제점이라.. 확실하게 이해가는 대목은 아니지만 그런 면도 있나보네요. 의존성이 개판인 경우는 그것부터 제대로 정리를 해야겠죠. 그런데 뭐 forward declaration만 모아놓은 헤더파일만 있어도 클래스 수백개인 프로젝트도 별 문제는 없습니다만 ㅎㅎ
Commented by zelon at 2008/06/30 23:35
제 홈페이지 중 위키에 있는 부분이라서 트랙백은 안되네요. 전에 적어둔 글 링크 하나 남깁니다.

http://wimy.com/wiki/wiki.php/linuxProgramming#s-4

gcc 로 precompiled header 쓰기입니다~
Commented by object at 2008/07/01 01:26
좋은 정보 감사합니다. 본문에 링크 추가하였습니다.
Commented by 몽몽이 at 2008/07/01 10:17
SSE, SIMD에 이어 깨달음을 주시는군요.
VC++ 쓰던 시절에도 PCH 보믄 이거 뭥미? 수준이었는데...
역시 다 이유가 있고 족보가 있는 물건이었군요.
전 사실 일부러 없애고 쓴 적도 많았는데.
아니나 다를까 공동으로 개발할땐 의존성이 개판인 코드를 만드는 사람들이 있어서...
흠... 이제 알았으니 걍 버리지 말고 심각히 고려해야겠습니다~
Commented by object at 2008/07/01 20:14
그런 사람 있으면 데려다가 개인면담을 좀 나누시기를 바랍니다.

예전 회사에 처음 들어갔을 때 소스코드를 보니 정말 개판이었는데요. 예를 들어, MFC가 만들어주는 CMainFrame mainfrm.h를 하나 고치면 거의 리빌드 올이 되었죠. 전혀 상관이 없어도 되는 파일도 그냥 인쿠르드 다 하고 정말 난리도 아니었습니다. 전방선언이 좀 문제를 일으키는 경우도 있으나 정말 이런 코딩 습관은 피해야죠.
Commented by 까막 at 2008/07/03 10:24
Apple의 XCode(툴체인이 gcc죠)를 써보면 기본으로 enable되어 있더군요. :)

사실 PCH는 PCH를 끄면 컴파일이 잘되는 경우가 있어서 사람들이 '귀찮은' 기능정도로 인식 하더군요. 원리도 잘 모르기도 하고...

gcc에서 PCH도입이 늦어진 이유는 아마 distcc(http://distcc.samba.org/)프로젝트때문이 아닌가 생각됩니다. IncrediBuild의 gcc버젼이랄까요. :) 왠만큼 큰 프로젝트들은 대부분 distcc를 활용하고 있더라구요.

아 그리고, 제가 써본 버젼까지는.. IncrediBuild에서 PCH지원을 안했던걸로 기억합니다. :)


ps. PCH도입이후 1시간안에 컴파일되는 솔루션을 보면서 행복했답니다. 잇힝
Commented by blueasa at 2010/10/21 17:23
좋은 글 잘보고 갑니다. :)

:         :

:

비공개 덧글

<< 이전 페이지 다음 페이지 >>





by 김민장 2008 이글루스 TOP 100
최근 등록된 덧글
개발자 입장에서의 수많은 ..
by Jiyoon at 02/04
저도 아들 돌잔치때 돌잡이 ..
by 박상욱 at 01/18
미국 대학원 원서 작성중에 p..
by 태클사이야 at 01/13
TO: 박PD 로그인 하지 않아..
by 박응용 at 01/10
http://gigglehd.com/zbx..
by dhunter at 12/28
우와.. 좋네요. 태반이 ..
by 윤광배 at 12/17
항상 좋은 글 잘 보고 있습니..
by y2k at 11/23
글이 좋아서 제 블로그에 담..
by 쏭섭 at 11/23
최근 등록된 트랙백
조엘 스폴스키의 강연 (Sta..
by 인덕원칸타타
[Redis] sds.c를 분..
by 조급하지말고 천천히
메뉴릿
이글루 파인더

website counter

Add to Google

rss

skin by 이글루스