큰 코드 기반 (컴파일) 문제에 대처하는 방법은 무엇입니까?


10

코딩 할 수는 있지만 아직 대규모 프로젝트를 수행 한 경험이 없습니다. 내가 지금까지 한 일은 몇 초 만에 컴파일되는 작은 프로그램을 코딩하거나 (알고리즘, 프로그래밍 원칙, 아이디어, 패러다임과 같은 다양한 c / c ++ 연습 또는 API를 시도하는 중 ...) 작은 프로젝트에서 작업하는 것입니다. 컴파일이 필요없는 스크립트 언어 (python, php, js)로 작성되었습니다.

문제는 스크립팅 언어로 코딩 할 때 무언가가 효과가 있는지 시도하고 싶을 때마다 스크립트를 실행하고 발생하는 것을 확인하는 것입니다. 문제가 해결되지 않으면 스크립트를 다시 실행하여 코드를 변경하고 다시 시도하여 원하는 결과를 얻을 때까지 계속 수행 할 수 있습니다. 내 요점은 기다릴 필요가 없다는 것입니다. 컴파일해야 할 부분이 많기 때문에 큰 코드 기반을 취하거나 수정하거나 추가하거나 간단하게 재생할 수 있습니다. 변경 사항을 즉시 볼 수 있습니다.

예를 들어 Wordpress를 사용하겠습니다. 플러그인을 만드는 방법을 알아 내려고 시도하는 것은 매우 쉽습니다. 먼저 간단한 "Hello World"플러그인을 작성하여 시작한 다음, 관리자 패널이 API에 익숙해 지도록 간단한 인터페이스를 만든 다음 API를 빌드하고 더 복잡한 것을 만들어보십시오. ". 작동하는 경우"와 "작동하는 방법"을 시도하기 위해 각각의 사소한 변경 후에 WP만큼 큰 무언가를 다시 컴파일해야한다는 아이디어는 비효율적이고 느리고 잘못된 것 같습니다.

이제 컴파일 된 언어로 작성된 프로젝트로 어떻게 할 수 있습니까? 일부 오픈 소스 프로젝트에 기여하고 싶습니다. 현명하게 생각 된 것 중 일부는 어떤 식 으로든 "모듈 식"인 반면, 다른 것들은 계속해서 다시 컴파일해야하는 하나의 큰 얼룩 일 것입니다.

이것이 올바르게 수행되는 방법에 대해 더 알고 싶습니다. 이에 대처하기위한 몇 가지 일반적인 관행, 접근 방식 및 프로젝트 설계 (패턴)는 무엇입니까? 이 "모듈화"는 프로그래머 세계에서 어떻게 불리며 이에 대해 더 배우려면 Google이 무엇을해야합니까? 프로젝트가 처음 생각한 비율에서 자라서 얼마 후에 문제가 되는가? 잘 설계되지 않은 프로젝트의 긴 컴파일 을 피할 수있는 방법이 있습니까? 어떻게 든 그것들을 모듈화하는 방법 (개발 중에 비 핵심 부분을 배제 할 수 있습니까 (다른 아이디어?))?

감사.


4
Ob. XKCD 및 관련 thinkgeek 티셔츠 * 8 ')
Mark Booth

1
충분한 예산으로 큰 프로젝트를 수행하면 컴파일 서버가 컴파일을 수행 할 수 있습니다 :)
SoylentGray

@ 차드-나는 그것을 알고 있지만, 그것은 단지 내 집의 gnu / linux 데스크탑 머신이고 지금은 나
뿐이다

@Chad Ok, Java (또는 다른 컴파일 된 언어) 대량을 처리하기위한 전용 서버 가 필요하다고 말씀 하십니까? 그것은 완전 쓰레기입니다
Kolob Canyon

1
@KolobCanyon-아니오 당신이 일할 수있는 규모가 필요하다고 말하고 있습니다. 빠른 컴파일 링 및 테스트 자동화 전용 온 디맨드 VM을 보유하는 것이 규모가 크지 않을 정도로 쉬워 지금은 충분히 저렴합니다.
SoylentGray

답변:


8

말한 것처럼 작은 변경을 할 때마다 전체 프로젝트를 다시 컴파일하지 마십시오. 대신 변경된 코드의 일부와 코드에 따른 모든 코드 만 다시 컴파일하십시오 .

C / C ++에서 컴파일은 매우 간단합니다. 당신은 컴파일 기계 코드에 각 소스 파일을 변환 한 다음 (우리는 그들이 파일 * .o 인 객체 호출) 링크 하나의 큰 실행 파일로 모든 오브젝트 파일을.

MainMa에서 언급했듯이 일부 라이브러리는 별도의 파일로 빌드되며 런타임에 실행 파일과 동적으로 연결됩니다. 이러한 라이브러리를 Unix에서는 공유 객체 (* .so)라고하고 Windows에서는 DLL (동적으로 링크 된 라이브러리)이라고합니다. 동적 라이브러리는 많은 장점이 있는데, 그 중 하나는 소스 코드가 효과적으로 변경되지 않는 한 컴파일 / 링크 할 필요가 없다는 것입니다.

다음과 같은 빌드 자동화 도구가 있습니다.

  • 소스 트리의 다른 부분 간의 종속성을 지정하십시오.
  • 수정 된 부분에서만 정확하고 신중한 컴파일을 시작하십시오.

가장 유명한 것 (make, ant, maven, ...)은 마지막 컴파일 이후에 변경된 코드 부분과 정확히 어떤 객체 / 바이너리를 업데이트해야하는지 자동으로 감지 할 수 있습니다.

그러나 이는 "빌드 스크립트"를 작성해야하는 비용이 상대적으로 적습니다. 타겟 및 의존성 정의, 원하는 컴파일러 정의 및 사용할 옵션 정의, 빌드 환경 정의, 라이브러리 경로 등 빌드에 대한 모든 정보를 포함하는 파일입니다. 유닉스 세계에서 공통) 또는 build.xml (Java 세계에서 매우 인기) 이것이 그들이하는 일입니다.


2
Ant (Java)는 재 컴파일해야 할 사항을 결정할 수 없습니다 . 변경된 소스 코드를 다시 컴파일하여 작업의 사소한 부분을 처리하지만 클래스 종속성을 전혀 이해하지 못합니다. 우리는이를 위해 IDE를 사용하며, 호출 코드를 변경할 필요가없는 방식으로 메소드 서명이 변경되면 잘못됩니다.
kevin cline

@kevincline 나는 두 번째이 - ANT 당신이에서 뭔가 다른를 지정하지 않는 한 모든 컴파일 build.xml파일
계산법 캐년

7

매번 전체 프로젝트를 다시 컴파일하지는 않습니다. 예를 들어, C / C ++ 애플리케이션 인 경우 라이브러리 (Windows의 DLL)로 분리 될 수 있으며 모든 라이브러리는 개별적으로 컴파일됩니다.

프로젝트 자체는 일반적으로 매일 밤 전용 빌드 서버에서 컴파일됩니다. 이 프로세스에는 컴파일 시간뿐만 아니라 단위 테스트, 기타 테스트 및 기타 프로세스 실행에 소요 된 시간도 포함되어 있기 때문에 많은 시간이 소요될 수 있습니다.


3
내가 다시 컴파일하지 않으면 언제 Trebuchet을 사용할
있습니까

5

나는 지금까지 모든 대답이 암시 한 것은 큰 소프트웨어 프로젝트는 거의 항상 훨씬 작은 조각으로 나뉘어져 있다는 것입니다. 각 조각은 일반적으로 자체 파일에 저장됩니다.

이 조각들은 개체 를 만들기 위해 개별적으로 컴파일 됩니다. 그런 다음 객체를 서로 연결 하여 최종 제품을 만듭니다. [어떻게하면 레고에서 물건을 만드는 것과 같습니다. 하나의 큰 플라스틱 조각으로 최종 재료를 성형하려고하지 않고 작은 조각들을 결합하여 만듭니다.]

프로젝트를 개별적으로 컴파일 된 조각으로 나누면 깔끔한 일이 발생할 수 있습니다.

증분 빌딩

먼저, 한 조각을 변경할 때 일반적으로 모든 조각을 다시 컴파일 할 필요는 없습니다. 일반적으로 말하면 다른 조각이 조각과 상호 작용하는 방식을 변경하지 않는 한 다른 조각은 다시 컴파일 할 필요가 없습니다.

이것은 점증적인 건물 이라는 아이디어를 낳습니다 . 증분 빌드를 수행 할 때 변경의 영향을받은 부분 만 다시 컴파일됩니다. 이것은 개발 시간을 크게 단축시킵니다. 사실, 모든 것이 다시 연결될 때까지 기다려야 할 수도 있지만 모든 것을 다시 컴파일하고 다시 연결해야하는 비용을 절약 할 수 있습니다. (BTW : 일부 시스템 / 언어는 증분 연결을 지원하므로 변경된 내용 만 다시 연결해야합니다. 일반적으로 비용은 코드 성능과 크기가 좋지 않습니다.)

단위 테스트

작은 조각이 있으면 두 번째로 할 수있는 것은 조각 이 결합 되기 전에 조각을 개별적으로 테스트하는 것입니다. 이것을 단위 테스팅이라고 합니다. 장치 테스트에서 각 장치는 나머지 시스템과 통합 (결합)되기 전에 개별적으로 테스트됩니다. 단위 테스트는 일반적으로 나머지 시스템을 사용하지 않고도 빠르게 실행할 수 있도록 작성됩니다.

테스트 적용의 제한 사례는 TDD (Test Driven Development)에 나와 있습니다. 이 개발 모델에서는 실패한 테스트를 수정하지 않는 한 코드를 쓰거나 수정하지 않습니다.

더 쉽게 만들기

따라서 문제를 해결하는 것이 좋지만 프로젝트를 빌드하는 데 많은 작업이 필요한 것 같습니다. 변경 한 부분과 해당 조각에 따라 달라지는 부분을 파악하고 각 조각을 컴파일 한 다음 모든 것을 연결해야합니다.

운 좋게도 프로그래머는 게으르다 * 그래서 작업을 쉽게 해주는 많은 도구를 발명했다. 이를 위해 위의 작업을 자동화하기 위해 많은 도구가 작성되었습니다. 이들 중 가장 유명한 것은 이미 언급되었습니다 (make, ant, maven). 이 도구를 사용하면 최종 프로젝트를 만들기 위해 어떤 조각을 조립해야하는지와 조각이 서로 어떻게 종속되는지를 정의 할 수 있습니다 (예를 들어 변경하면 다시 컴파일해야 함). 결과적으로 단 하나의 명령을 실행하면 재 컴파일해야 할 내용을 파악하고 컴파일 한 후 모든 것을 다시 연결할 수 있습니다.

그러나 그것은 여전히 ​​사물이 어떻게 관련되어 있는지 알아내는 것입니다. 그것은 많은 작업이며 이전에 말했듯이 프로그래머는 게으르다. 그래서 그들은 다른 종류의 도구를 생각해 냈습니다. 이 도구는 사용자를위한 종속성을 결정하기 위해 작성되었습니다! 도구는 종종 Eclipse 및 Visual Studio와 같은 IDE (Integrated Development Environments)의 일부이지만 일반 및 특정 응용 프로그램 (makedep, QMake for Qt 프로그램)에 사용되는 일부 독립형 도구도 있습니다.

* 실제로 프로그래머는 게으르지 않으며 프로그램에서 자동화 할 수있는 반복적 인 작업을하지 않고 문제를 해결하는 데 시간을 투자하고 싶어합니다.


5

C / C ++ 빌드 속도를 높이기 위해 시도 할 수있는 내용은 다음과 같습니다.

  • 변경된 사항 만 재구성하도록 설정 했습니까? 대부분의 환경은 기본적으로이 작업을 수행합니다. 파일이 변경되거나 헤더가 변경되지 않은 경우 파일을 다시 컴파일 할 필요가 없습니다. 마찬가지로 objs / lib에 연결된 모든 항목이 변경되지 않은 경우 dll / exe를 다시 빌드 할 이유가 없습니다.
  • 절대 변경되지 않는 타사 항목 및 관련 헤더를 일부 읽기 전용 코드 라이브러리 영역에 배치하십시오. 헤더와 관련 바이너리 만 필요합니다. 한 번이 아닌 다른 소스에서 이것을 다시 빌드 할 필요 는 없습니다 .
  • 모든 것을 재 구축 할 때 필자의 경험에서 두 가지 제한 요소 는 코어 수디스크 속도 였습니다. 정말 좋은 HDD를 갖춘 강력한 쿼드 코어 하이퍼 스레딩 머신을 사용하면 성능이 향상됩니다. 솔리드 스테이트 드라이브를 고려하십시오. 저렴한 드라이브는 좋은 하드 디스크보다 나쁠 수 있습니다. HDD를 높이기 위해 습격 사용을 고려하십시오
  • 네트워크의 다른 워크 스테이션에 컴파일을 분할하는 Incredibuild 와 같은 분산 빌드 시스템을 사용하십시오 . 네트워크가 안정적인지 확인하십시오.
  • 지속적으로 헤더 파일을 다시로드하지 않도록 단일 빌드 를 설정 하십시오.

내 경험상 (많지 않지만 잘) 디스크 속도가 프로젝트가 "매우 작은"수준을 넘어 서면 무의미 해지기 시작합니다. 다음 글에서 생각하는 것을 생각해보십시오. 컴파일 속도를 높이기 위해 네트워크를 사용하고 있습니다. 디스크에 큰 병목 현상이 발생한 경우 네트워크를 사용하는 것이 그리 좋은 방법은 아닙니다.
R. Martinho Fernandes

또 다른 저렴한 솔루션은 tmpfs로 컴파일하는 것입니다. 컴파일 프로세스가 IO 바운드 인 경우 성능을 크게 향상시킬 수 있습니다.
Artefact2

4

"작동하는 경우"와 "작동하는 방법"을 시도하기 위해 각각의 사소한 변경 후에 WP만큼 큰 것을 다시 컴파일해야한다는 아이디어는 비효율적이며 느리고 잘못된 것 같습니다.

해석 된 것을 실행하는 것도 매우 비효율적이고 느리며 (논쟁 적으로) 잘못되었습니다. 개발자 PC의 시간 요구 사항에 대해 불평하고 있지만 컴파일 하지 않으면 사용자 PC 시간 요구 사항이 발생하기 때문에 아마도 훨씬 더 나쁩니다.

더 중요한 것은 현대 시스템은 매우 고급 증분 재 구축을 수행 할 수 있으며 사소한 변경을 위해 전체를 다시 컴파일하는 것은 일반적이지 않습니다. 컴파일 된 시스템에는 스크립트 구성 요소, 특히 UI와 같은 것들이 포함될 수 있습니다.


1
나는 내 질문이 해석 접근법 토론과 해석하기위한 것이 아니라고 생각합니다. 대신 방금 (컴파일 된) 대규모 프로젝트의 개발이 올바르게 수행되는 방법에 대한 조언을 요청했습니다. 그래도 점진적 재구성 아이디어에 감사드립니다.
pootzko

@pootzko : 글쎄, 해석의 단점에 대해 이야기하지 않을 때 컴파일의 단점을 논의하는 것은 불공평합니다.
DeadMG

1
아니에요 그것은 또 다른 토론이며 내 질문과 관련이 없습니다. 나는 그것이 논의되어서는 안되는 것이라고 말하고 있지 않습니다. 여기서는 안됩니다.
pootzko

@ pootzko : 그렇다면 당신은 대부분의 질문을 컴파일에 대해 싫어하는 것을 열거하는 데 헌신해서는 안됩니다. "대규모 프로젝트의 컴파일 시간을 어떻게 줄일 수 있습니까?"와 같이 더 짧고 간결한 것을 작성해야합니다.
DeadMG

나는 내가 어떻게 "내가 질문을해야"하는지 누군가에게 물어봐야한다는 것을 몰랐다. : OI는 내 관점을 더 잘 설명하여 다른 사람들이 더 잘 이해하고 컴파일 된 언어로 동일하거나 유사한 것을 달성하는 방법을 설명 할 수 있도록 작성했습니다. 해석 된 언어가 사용자 PC의 시간 요구 사항을 악화시키는 지 다른 사람에게 말해달라고 요청했습니다. 나는 그것을 알고 있으며 내 질문과는 아무런 관련이 없습니다- "어떻게 컴파일 된 언어로 수행됩니까?", 죄송합니다. 다른 사람들은 내가 무엇을 요청했는지 알아 낸 것 같습니다. 그래서 나는 내 질문이 충분히 명확하지 않다고 생각하지 않습니다 ..
pootzko

4
  • 부분 재구성

프로젝트가 적절한 컴파일 종속성 DAG를 구현하면 변경 사항에 영향을주는 개체 파일 만 다시 컴파일하면됩니다.

  • 다중 컴파일 프로세스

또한 적절한 컴파일 종속성 DAG를 가정하면 여러 프로세스를 사용하여 컴파일 할 수 있습니다. 코어 / CPU 당 하나의 작업이 표준입니다.

  • 실행 가능한 테스트

테스트를 위해 특정 오브젝트 파일 만 링크하는 여러 실행 파일을 작성할 수 있습니다.


2

MainMa의 답변 외에도 우리는 작업중 인 기계를 업그레이드했습니다. 우리가 가장 잘 구입 한 것 중 하나는 전체 프로젝트를 다시 컴파일하는 데 도움이 될 수없는 SSD였습니다.

다른 제안은 다른 컴파일러를 시도하는 것입니다. 그 당시에는 Java 컴파일러에서 Jikes로 전환했으며 이제 멀티 코어 프로세서를 더 잘 활용하는 Eclipse (이름이 있는지 모름)와 함께 번들로 제공되는 컴파일러를 사용했습니다.

37,000 개의 파일 프로젝트를 수정하기 전에 처음부터 컴파일하는 데 약 15 분이 걸렸습니다. 변경 후 2-3 분으로 줄었습니다.

물론 MainMa의 요점을 다시 언급 할 가치가 있습니다. 변경 사항을보고 싶을 때마다 전체 프로젝트를 다시 컴파일하지 마십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.