분류정리

2009/06/09 03:46
뭔가 글을 써 놓고 그것이 보존되고 활용되는걸 지켜보는건 재미있고 흐뭇하다.
특히 시험기간처럼 막막한 기간에는 옛날글들이 작은 웃음을 띄게 해주는 고마운 존재다.

오랫만에 블로그 분류를 정리했다.
이 블로그를 운영한지 벌써 3년 가까이 지난걸 보면, 세월은 잘도 흐른다.

윈도우 / 리눅스 분류 이외에 멀티플랫폼이라는 분류를 추가했다.
오픈소스 프로그램 덕분에 플랫폼에 덜 구애받게 된것은 정말 개발자나 유저로써 행운이다.

영화나 드라마, 만화등을 문화산업이라는 분류로 정리했다.
문화산업이라는게 부정적인 어감이 많은 단어이긴 하지만, 내가 접하는 많은 '컨텐츠'가 역시 대량 생산된 산업의 생산물이라는것도 받아들이는게 맞는것 같다.

컴퓨터 공학이나 그런것들은 프로그래밍으로 통합해버렸다.
컴퓨터에 관련된 잡담이나 그런것도 그냥 다 프로그래밍으로 밀어넣으려고 생각중이다.
예전보다 훨씬 컴퓨터에 대한 낭만이 사라진건 사실이지만, 요거이가 또 재미있는것도 사실이다.

30이 되기전에 좀더 여유를 가지고, 내가 해왔던것들을 다듬고 돌이켜보고 싶은데 현실속 나는 내일의 기말고사를 걱정하는 대학생이다. 예전의 내 고민들을 부정하는것은 아니지만, 좀더 치열하고 밀도높게 살지못한것이 후회되는건 어쩔수 없는것 같다.

여유라는게 마음먹기 나름이라, 이런식의 마음가짐이면 평생 쫓기듯이 살것이 뻔하지만, 여하튼 빵점은 면해야하지 않겠는가? (-_-털썩..)

여하튼, 시험공부중에 예전글들을 읽으며 여유한번 부려봤다.
(근데, 이글 바로 전 '일상이야기'가 시험기간 이라는 글이네...-_-)

일상 이야기 기말고사, 주저리

썬더버드 ThreadVis

2009/04/06 22:08
메일링 리스트를 자주사용하는 사람에게는 '쓰레드로 글 읽기'라는 썬더버드 기능이 참 편리하다. ThreadVis는 이러한 쓰레드관리기능을 강화해주는 썬더버드 익스텐션이다.

ThreadVis02

보낸사람있는 패널 오른쪽으로 보이는, 회색네모와 파란네모 그리고 그 네모들을 연결하는 선이 ThreadVis의 인터페이스다. 파란네모가 지금 내가 보고 있는 메일이고 연결선들은 어떤 쓰레드로 연결되어 있는지를 알수 있게 해준다. 저 네모들은 클릭이 가능하여 읽고 있는 쓰레드의 부모로 바로 가는것이 가능하다.

'별표'상태는 썬더버드에 오래전부터 있던 기능인데 이렇게 별표를 찍어두고 '검색폴더'기능으로 '별표'라는 폴더를 만들어두면, 내가 이 계정에서 별표해놓은 메일을 바로 검색할수 있어서 편리하다.

ThreadVis02

네모들중에 속이 비어있는 네모가 있는데 그것은 내가 작성한 메일을 의미한다. 역시 클릭이 가능하며 쓰레드간의 이동이 편리하다. '검색폴더'를 만드는 가장쉽고 또 가장 강력한 방법은 오른쪽 상단에 있는(돋보기에 '제목'이라고 써있는) 검색필터를 통해서 만드는 방법이다. 원하는 필터종류로 필터링을 한후에 바로 검색폴더로 만들수 있다. 글로 적자니 조금 장황한데, 써보면 직관적이라서 바로 알수 있을것이다.

다른 검색폴더 만들기 방법도 있지만 이 방법을 추천하는 이유는, 다른 방법으로 만들어진 검색폴더에서는 쓰레드 - 번역이 적절하게 '글타래'로 되어있다 - 보기가 안되고 이 방법으로 만들어진 폴더에서만 글타래보기가 가능하기 때문이다. 썬더버드 버그인지 아니면 내가 잘 모르는것인지 모르겠지만, 하여튼 저방법으로 검색폴더를 만들면 메시지리스트 창에서 글타래로 정렬해 볼 수 있다.

멀티플랫폼/실행환경 메일링리스트, 썬더버드

재컴파일 속도 올리기

2009/03/25 22:45
사실 나는 컴파일이 느려서 불만이었던적은 거의 없는데 make 파일을 작성하다가 (재)컴파일 속도를 올리는 방법을 컴파일러 입장에서 생각해보게 되었다.

컴파일을 할때 .o를 새로 만들필요가 없으면 컴파일 안하는게 가장 빠른 방법일것이다. 그래서 make는 target과 src의 업데이트를 비교해 src 파일이 업데이트가 없으면 컴파일을 수행하지 않는다.(make와 그 친구들 참조)

근데 이 작업에 의외의 난관이 있는게, c에서 include 하고 있는 헤더가 변경되면 어떻게 될것인가 여부다. 즉, c파일이 변경되었는지 아닌지를 판별하기 위해서는 .c파일과 .o 파일의 시간확인만으로는 안되고 .c파일이 의존하고 있는 .h파일들과 .o 파일의 시간확인이 필요하다.

.c파일이 include하고 있는 헤더를 확인하기위해 많이 쓰는방법이 makedep같은 의존성 확인툴을 사용하는것이다. 또 다른방법으로는 gcc -M 옵션으로 include되는 의존성을 확인하는 방법이 있다. 의존성을 확인할때는 #ifdef 같은것으로 include가 제한될수 있으므로 플래그 옵션까지 넣어서 확인하는게 일반적이다.

만일 헤더가 다른 헤더를 include하고 있다면 다시 그 include하고 있는 파일까지 일일이 .o파일과 비교해봐야 할것이다. 만일 그렇게 하지 않으려면 의존성 확인은 .c파일의 헤더만 확인하고 대신에 .c파일에서는 모든 헤더를 다 써주겠다는 프로젝트 고유의 룰을 만들고 그것을 바탕으로 make 파일을 작성해 주어야 할것이다.(gcc를 사용하면 소스파일만 적어넣어주면 .c파일과 .o 파일에 관련된 모든 종속파일들을 다 보여준다. 만일 gcc -MM 옵션을 주면 시스템 헤더등은 제외한다.)

비주얼 스튜디오를 사용하면 이런 세세한 설정을 할 수는 없지만 이녀석도 사람이 만든이상 비슷한 일을 할 것이다. 잘 알려진 좀더 나은 방법으로 삼바 프로젝트에서 한것처럼 변경사항관리같은것을 해슁해서 캐싱하고 있다가 그것을 토대로 변경사항을 확인하는 방법등이 있으니 그것을 사용하고 있을지도 모르겠다.(모르긴 몰라도 이런식의 방법이 아니면 비주얼 스튜디오가 F5를 눌렀을때 번개같이 실행하는것은 납득할수 없다. 일단 변경된지를 체크해야 하는데 그것이 위에서 말한것처럼 쉽지 않기 때문이다.)

어쨌거나 이렇게 복잡하게 얽긴 헤더는 확실히 컴파일 속도를 느리게 하는 원인이다. 복잡하게 얽힌 의존성을 확인하는데 걸린 시간이 그냥 컴파일을 하는데 걸린 시간과 비슷해질지도 모를일이다. 그래서 우선 컴파일 속도를 빠르게 하려면 헤더 종속성 문제를 코딩단계에서 고려해야 한다.

만일 .o 파일이 아닌 .a 파일(즉, 라이브러리로) 만든다면, include 의존성을 확인할 필요가 없이 .a 파일과 관련된 모든 파일들과 .a 파일의 업데이트 시간만을 비교하는것으로 재컴파일을 할지를 결정할수 있다. 내가 이 방법을 써봤는데 확실한 속도 향상이 있었다.

그래서 라이브러리를 만들어내는 중간 프로젝트들을 많이 만들어 배치하는것이 전체적인 컴파일 속도를 올리는 또 다른 방법이 될 수 있다.

이런식의 테크닉들을 적용하려고 보면 makefile을 작성하는것이 정말 아스트랄해진다. 그래서 내가 선택한것은 rake였는데 굉장히 만족하면서 사용하고 있다.

아래는 앞에서 말한 로직을 만족하는 rakefile 내 함수의 일부이다.
(Language : perl)
i = 0
size = files_to_check.length
while i < size
    break unless uptodate?(target, files_to_check[i])
    i += 1
end

# do not need build
return if i == size

# need to compile
updated_objects = 0
srcs.each do | fullPath |
    #puts fullPath
    gcc_mm = "gcc -MM #{include_flags} #{fullPath}"
    result = `#{gcc_mm}`.split
    object_file = result[0].chomp(':')
    object_file.gsub!(/\.o$/, '_g.o') if @with_debug_symbol
    need_compile = uptodate?(object_file, fullPath) ? false : true
    unless need_compile
        2.upto(result.length-1) do | result_index |
            dependent_header = result[result_index]
            #puts dependent_file
            if ( dependent_header != "\\" ) \
                and ( dependent_header.include?("wxWidgets-2.8.9") == false ) \
                and ( dependent_header.include?("/usr/") == false ) \
                and ( uptodate?(object_file, dependent_header) == false )
                puts "#{object_file} will be recompiled because #{dependent_header} was changed"
                need_compile = true
            end
            break if need_compile
        end
    end
    #compile
    if need_compile
        compiler = ( fullPath.match(/.*\.cpp$/) != nil )? 'g++' : 'gcc'
        compiler << " -g -o #{object_file}" if @with_debug_symbol
        sh "#{compiler}#{include_flags} -O3 -c #{fullPath}"
    end

    lib_flags_head << ' ' + object_file
    updated_objects += 1 unless uptodate?(target, object_file)
end

전체 소스는 여기서 볼수 있다. .h와 .c 파일의 의존성은 는 gcc( -MM옵션)를 이용해 파악하고 있다. uptodate? 라는 함수가 파일간의 timestamp를 확인하는 함수이다. .a를 빌드해내는 프로젝트라면 앞에서 말한것처럼 files_to_check 라는 배열에 .a를 만드는데 관여하는 모든 파일을 넣고 그것들의 변경여부를 확인한다.

rake로 만들어 생기는 다른 장점으로는 Hudson에 연동하기가 매우 쉽다는 점이다. 내가 Hudson에 rake 작업들을 등록하고 맨 처음에 해본일이 과연 내가만든 빌드규칙과 MS의 빌드 규칙중 누가더 빠른지를 확인하는거였는데, 물론 clean상태의 컴파일 속도가 아니라 변경사항이 일부 있을때의 재컴파일 속도이다.

hudson_rake_build

위의 스샷처럼 루비 Rake를 통해 직접 작성한 gcc_debug 가 동일한 조건에서 msbuild를 이용하여 컴파일한 vc_debug 보다 6배 이상 빠르다! 흐흐.

-_- 세줄요약
1. 헤더 종속성을 고려하자
2. 라이브러리 프로젝트를 잘 활용하자.
3. rake 만세.

프로그래밍 Development, rake, 루비, 빌드