Development

빌드 성능 개선 (최적화)

chbae 2024. 7. 25. 02:54
728x90

작년 10월 https://www.yocto.co.kr/176 글에서 Yocto 빌드 성능 최적화에 대해서 글을 썼고 중간중간 clang 적용, ccache 적용 등 회사에서 작업한 내용들을 간단히 적어보았다.

 

이 글에서는 일반론적인 임베디드 소프트웨어 개발에서 빌드 성능을 개선할 수 있는 작업들을 경험을 토대로 적어보고자 한다. Yocto Linux, QNX, 안드로이드 등 OS를 포함하는 빌드에서 성능을 개선하는데 큰 그림이 될 수 있을 것으로 생각된다.

출처: https://linuxgizmos.com/open-source-project-aims-to-build-embedded-linux-hypervisor/

 

차량용 ECU가 여러 개에서 하나로 통합되면서 고성능의 SoC가 필요하고 그 위에 하이퍼바이저 기반으로 여러개의 OS가 올라가서 동작한다. 이 각각의 OS를 빌드하는데도 오랜 시간이 걸리고 클라우드를 사용하면 그 비용을 상당히 많이든다. 현재 프로젝트가 그렇고 지속적으로 성능을 향상시키는 작업을 진행중에 있다.

 

어제는 컨설팅 회사와 미팅을 했고 그들과의 관심사는 클라우드 비용 최적화였다. 자연스럽게 빌드 성능 향상이 비용 최적화로 이루어지지만 정책적인 부분도 많이 차지하기도 한다.

 

솔직히 프로젝트를 들여다보면 정말 많은 부분에서 클라우드 인프라 비용을 최적화 할 수 있는 부분이 많이 보이기도 한다. 팀의 AWS 클라우드를 운영하면서도 마찬가지고 실제로 비용을 많이 줄이기도 했다.

빌드 성능 향상 방법

1. 최신 세대의 CPU 사용: 당연히 이전세대보다 Core 한개의 속도가 빠르다. 현재 AWS는 intel 기준으로 7세대를 지원한다.

2. 최적의 AWS Instance Type 사용: 정확히 말하면 비용 절감이 크다. 예를 들어 m으로 시작하는 type은 general하는 것으로 c로 시작하는 computing 최적화 type에 비해서 더 많은 ram을 가지고 있어 비싸다. 이런 부분을 잘 고려해서 결정하면 많은 비용을 절약할 수 있다.

3. AMD 또는 Graviton 사용 검토: AMD가 Intel에 비해서 저렴하고 빌드 성능도 가끔 더 좋다. 하지만 아주 이전 세대 AMD Ryzen 을 선택하면 병렬 빌드할 때 segfault가 뜨는 경우가 종종 발생해서 권장하지 않았다. 하지만 테스트 해보고 더 이상 발생하지 않으면 비용 최적화를 위해서도 검토하는 것이 좋다. Graviton은 arm64 아키텍처로 비용은 더 싸지만 빌드가 지원 안하는 경우도 있어 추가적인 검토가 더 필요하다.

4. 컴파일러 변경 (gcc -> clang): 특히 clang의 장점은 빌드 프로파일 및 다양한 도구 지원, 병렬 링커 지원 등으로 링킹 작업에 시간이 많이 드는 컴포넌트를 사용할 때 적용하는 것을 강력히 추천한다. 실제로 특정 컴포넌트에서 5시간 -> 15분, 1시간 30분 -> 20분이 줄어드는 놀라운 경험을 했다. https://www.yocto.co.kr/288 글을 한번 더 읽어보기 바란다.

5. 캐시 사용: Incremental build는 무조건 사용하는 것을 추천한다. Yocto Linux는 제공하는 shared state cache와 ccache를 조합해서 사용하는 것을 추천한다. Bazel도 cache를 잘 사용할 수 있게 제공해서 무조건 추천하고, cmake, make기반의 c/c++ 코드를 사용하면 ccache를 따로 적용하는 것을 추천한다.

6. S3 bucket 사용: AWS에서 공유하는 공간을 EFS로 많이 사용하는데 이를 S3 bucket 사용을 고려해볼 수 있다. 엄청난 클라우드 비용을 절약할 수 있다.

7. Retention 정책: 캐시나 아티팩트를 얼마나 오랫동안 유지하는지에 대한 정책을 프로젝트 맞게 결정해야한다. 생각보다 저장공간으로 클라우드 비용이 많이 든다.

8. 의존성 정리: 불필요한 빌드 시간의 의존성을 없애고 컴포넌트간 의존성을 아키텍처적으로 최적화 한다.

9. MR (Merge Request) / PR (Pull Request) 빌드 최적화: 이상적으로 모든 이미지 빌드와 타겟에 대한 빌드를 MR/PR 별로 해야한다. 하지만 반대로 엄청난 비용이 든다. 이 부분을 프로젝트에 맞게 잘 정리하는 것이 좋다.

10. 랜덤 파이프라인 이슈 최적화: 랜덤 이슈로 인해 빌드 에러가 나면 개발자들은 다시 빌드를 트리거 한다. 당연히 이때 클라우드를 사용할 경우 비용이 발생한다.

11. Yocto 레시피 최적화: 레시피가 제대로 구성되어 있지 않으면 Yocto cache (Shared State Cache) hit이 잘 되지 않는다. 이 부분을 주기적으로 검토하여 수정한다.

12. 빌드 트리거 최적화: 필요할 때만 빌드하도록 트리거를 설정하여 불필요한 빌드를 줄인다. 예를 들어, 코드 변경이 있을 때만 빌드를 트리거하도록 설정한다. 

 

이 외에도 다양한 노력들이 프로젝트에 맞게 적용될 수 있다. 업무를 진행하다가 좋다고 생각하는 내용들이 있으면 계속 기록해보려고 한다. 단 너무 최적화와 비용만 신경쓰다가 실제 개발에 꼭 필요한 부분까지 제거해버리면 나중에 다른 부분에서 추가적인 비용이 들기 때문에 장단점을 잘 비교해서 진행하기 바란다.