엔지니어링 문서

Cloud Mac 지속 빌드의 열 스로틀링 진단

Cloud Mac 지속 빌드의 열 스로틀링 진단

Cloud Mac에서 동일한 커밋을 연속으로 빌드했을 때 첫 번째 빌드는 11분이었지만 네 번째 빌드는 15분으로 늘어났더라도, 곧바로 “머신 성능이 불안정하다”고 결론 내리면 안 됩니다. 캐시 적중 여부, 인덱싱 프로세스, 테스트 동시 실행, 열 압력 모두 비슷한 양상의 원인이 될 수 있습니다. 올바른 진단 방법은 변수를 고정하고 연속으로 측정한 뒤, 빌드 시간 증가가 전력 소비 및 열 압력과 동시에 나타나는지 확인하는 것입니다.

비교 가능한 빌드 샘플부터 정의하기

진단 대상은 개발자가 임시로 클릭한 Scheme이 아니라 안정적으로 재현할 수 있는 명령이어야 합니다. 코드 커밋, Xcode 경로, SDK, 대상, 빌드 구성, DerivedData 디렉터리를 고정하고 머신 부팅 후 유휴 시간도 기록합니다. 실행할 때마다 브랜치를 전환하거나 종속성을 업데이트하면 워크로드 변화만 측정하게 됩니다.

VMOrbit의 전용 물리 노드에서는 다른 테넌트의 가상 머신 스케줄링이 호스트 리소스에 영향을 주지 않습니다. 하지만 노드 내부에서는 여전히 인덱싱, 종속성 해석, 시뮬레이터, 이전 빌드 프로세스가 서로 리소스를 두고 경쟁할 수 있습니다. 시작하기 전에 기본 환경 정보를 저장합니다.

mkdir -p "$HOME/build-thermal-check"
system_profiler SPHardwareDataType > "$HOME/build-thermal-check/hardware.txt"
xcodebuild -version > "$HOME/build-thermal-check/xcode.txt"
pmset -g > "$HOME/build-thermal-check/power.txt"
ps -axo pid,%cpu,%mem,etime,command > "$HOME/build-thermal-check/processes-before.txt"

콜드 빌드와 웜 빌드를 분리해 측정하기

콜드 빌드는 전체 컴파일 부하를 관찰하는 데 사용하고, 웜 빌드는 증분 빌드 경로를 확인하는 데 사용합니다. 두 결과를 동일한 통계 그룹에 섞어서는 안 됩니다. 콜드 빌드에는 새 전용 DerivedData를 사용하고, 웜 빌드는 직전 실행의 디렉터리를 재사용합니다. 노드의 다른 작업에 영향을 줄 수 있으므로 전역 캐시는 정리하지 마십시오.

샘플 DerivedData 주요 용도
콜드 빌드 그룹마다 다시 생성 전체 컴파일의 지속 부하 비교
웜 빌드 동일 그룹에서 재사용 증분 빌드와 캐시 효과 확인
유휴 상태 대조군 빌드하지 않음 백그라운드 프로세스와 기준 전력 소비 식별

빌드 시간과 열 압력을 함께 수집하기

전체 빌드 시간만으로는 열 스로틀링을 입증할 수 없습니다. 최소 3회 연속 실행하고 빌드 중에 powermetrics도 함께 수집해야 합니다. 이 도구에는 일반적으로 관리자 권한이 필요하므로, 권한 부여 범위를 명확한 명령과 매개변수로 제한해야 합니다.

RUN_ROOT="$HOME/build-thermal-check/run-01"
mkdir -p "$RUN_ROOT/DerivedData"

sudo powermetrics --samplers cpu_power -i 1000 -n 900 \
  -o "$RUN_ROOT/powermetrics.txt" &
METRIC_PID=$!

/usr/bin/time -lp xcodebuild \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -derivedDataPath "$RUN_ROOT/DerivedData" \
  build > "$RUN_ROOT/build.log" 2> "$RUN_ROOT/time.txt"

wait "$METRIC_PID"
pmset -g therm > "$RUN_ROOT/thermal.txt"

-n 900은 최대 900회 수집한다는 의미입니다. 빌드가 더 일찍 끝나도 백그라운드 샘플링은 계속됩니다. 프로젝트 스크립트에서 빌드 종료 후 샘플링 프로세스에 TERM을 보낼 수 있지만, CI에 샘플링 프로세스가 남지 않도록 종료 처리 로직을 반드시 유지해야 합니다. powermetrics를 사용할 수 없다면 최소한 pmset -g therm, time -lp, CPU 사용량순으로 정렬한 프로세스 스냅샷을 저장하십시오.

열 스로틀링은 “소요 시간 추세”와 “시스템 신호”가 함께 뒷받침해야 내릴 수 있는 결론입니다. CPU 사용률이 한 번 높았다는 이유만으로 확정할 수 있는 진단명이 아닙니다.

단일 측정값이 아닌 추세로 판단하기

각 실행의 실제 소요 시간, 최대 상주 메모리, 열 압력, 같은 시간대의 고부하 프로세스를 하나의 기록표에 정리합니다. 첫 번째 실행은 느리지만 이후 실행이 눈에 띄게 빨라진다면 일반적으로 캐시 워밍 효과입니다. 특정 실행만 갑자기 느려지고 동시에 종속성 다운로드나 인덱싱 프로세스가 나타났다면 리소스 경합일 가능성이 더 큽니다.

더 주의 깊게 살펴야 할 패턴은 다음과 같습니다. 코드와 캐시 상태가 동일한데도 여러 차례 연속 실행할수록 소요 시간이 점진적으로 늘어나고, CPU가 장시간 최대 부하로 작동하며, 그에 따라 열 압력 신호도 상승하고, 부하를 중단한 뒤 유휴 상태로 두면 다음 실행에서 성능이 회복되는 경우입니다. 이러한 증거가 모두 함께 나타날 때만 열 스로틀링을 주요 원인으로 판단해야 합니다.

흔한 오탐 세 가지 배제하기

먼저 빌드가 테스트, 아카이브 또는 스크립트 다운로드를 암묵적으로 실행했는지 확인합니다. 다음으로 로그에 기록된 컴파일 파일 수를 비교하여 각 실행의 작업량이 동일한지 검증합니다. 마지막으로 여러 xcodebuild, 시뮬레이터 또는 패키지 관리 프로세스가 병렬로 실행되고 있는지 확인합니다. 이상이 발생한 실행에서는 다음 정보를 저장할 수 있습니다.

date -u
pgrep -alf 'xcodebuild|swift-frontend|clang|Simulator'
top -l 3 -o cpu -stats pid,command,cpu,mem,time
du -sh "$RUN_ROOT/DerivedData"

top의 순간 순위는 샘플링 시점에 어떤 프로세스가 리소스를 사용했는지만 보여 줄 뿐, 그 자체로 근본 원인을 입증하지는 못합니다. 시스템 상태와 프로젝트 워크로드를 연결하는 근거는 빌드 로그에 기록된 작업 수와 지속 시간입니다.

대조 실험으로 발생 조건 찾기

추세를 확인한 뒤에는 한 번에 하나의 변수만 변경합니다. 먼저 다른 조건은 그대로 유지한 채 CI 동시 작업 수를 1로 줄입니다. 그다음 동시 작업 수를 복원하고 시작 시간을 분산합니다. 마지막으로 콜드 빌드와 웜 빌드를 비교합니다. 동시 작업 수를 줄인 뒤 소요 시간 추세가 안정된다면 컴파일러 자체의 성능 저하보다는 동일 노드 내 작업 경합이나 지속적인 고전력 소비가 원인일 가능성이 큽니다.

더 공격적인 캐시 정리를 곧바로 해결책으로 사용하지 마십시오. 캐시를 정리하면 다음 실행의 작업량이 증가하고 기존 추세가 가려집니다. 재부팅도 유일한 근거로 삼아서는 안 됩니다. 재부팅은 백그라운드 프로세스를 종료하고 일부 상태를 초기화하는 동시에 냉각 시간까지 제공하므로, 어떤 변화가 실제로 효과를 냈는지 판단할 수 없습니다.

순간적인 클록 속도보다 빌드 스케줄링 조정하기

안정적인 해결책은 일반적으로 동일 노드에서 실행되는 고부하 작업 수를 제한하고, 아카이브·전체 테스트·정적 분석의 실행 시간을 분산하며, 각 파이프라인에 독립적인 DerivedData를 할당하는 것입니다. 반드시 병렬로 실행해야 하는 작업은 동시 실행 수가 1, 2, 3일 때의 중앙 소요 시간을 먼저 측정한 뒤, 단일 작업의 최고 성능이 아니라 전체 처리량이 가장 높은 단계를 선택합니다.

진단 결과를 CI 기준선으로 정착시키기

기준선에는 명령, 커밋, Xcode 버전, 빌드 유형, 연속 실행 횟수, 중앙 소요 시간을 저장해야 합니다. 가장 빠른 실행을 기준으로 삼지 말고, 한 번의 시간 초과만으로 병합을 차단해서도 안 됩니다. 최근 여러 실행의 중앙값을 롤링 방식으로 비교하고, 임계값을 연속으로 여러 번 초과했을 때 진단 기록을 생성하는 규칙이 더 안정적입니다.

최종 결과물에는 최소한 빌드 로그, time 출력, 열 압력 기록, 프로세스 스냅샷, 샘플링 매개변수가 포함되어야 합니다. 문제를 상위 단계로 전달해야 한다면 노드 리전, 발생 시간, 재현 절차, 필요한 최소한의 로그를 첨부하되 비밀번호, 개인 키 또는 전체 액세스 자격 증명은 제출하지 마십시오. 이렇게 하면 비슷한 변동이 다시 발생했을 때 팀이 원인을 처음부터 추측하지 않고 동일한 샘플을 즉시 다시 실행할 수 있습니다.

자주 묻는 질문

Xcode 빌드 한 번이 느려졌다면 열 스로틀링으로 볼 수 있나요?

아닙니다. 코드, Xcode 버전, 캐시 상태와 병렬도를 고정한 뒤 최소 세 번 연속 실행하고 CPU 전력, 열 압력, 백그라운드 프로세스를 함께 비교해야 합니다.

powermetrics 실행에는 관리자 권한이 필요한가요?

일반적으로 필요합니다. 허용된 인자만 사용하는 제한된 sudo 명령으로 수집하고 결과를 통제된 디렉터리에 저장하는 방식이 안전합니다.

전용 물리 노드

빌드 작업을 전용 클라우드 Mac에서 실행하세요

VMOrbit M4 또는 VMOrbit M4 Pro를 선택하고 팀의 위치에 따라 노드를 지정하세요. 실제 사용 가능 여부와 제공 정보는 콘솔에서 실시간으로 확인되는 내용을 기준으로 합니다.

클라우드 Mac 선택