SureVM 엔지니어링 노트

클라우드 Mac CI 프로세스 우선순위 관리 방법

클라우드 Mac CI 프로세스 우선순위 관리 방법

하나의 클라우드 Mac에서 Xcode 빌드, 테스트, 로그 압축, 산출물 검증을 동시에 실행할 때 가장 흔한 문제는 특정 프로세스 하나가 완전히 통제 불능 상태에 빠지는 것이 아닙니다. 대부분은 조금 늦게 끝나도 되는 여러 보조 작업이 핵심 빌드와 CPU, 디스크, 메모리 대역폭을 두고 경쟁하면서 발생합니다. 그 결과 컴파일 시간이 들쭉날쭉해지거나 테스트가 시간 초과로 실패하고, 원격 데스크톱 응답이 느려질 수 있습니다. 이런 문제를 해결하려면 모든 프로세스의 우선순위를 무작정 낮추기보다 먼저 핵심 경로와 백그라운드 경로를 구분해야 합니다.

비교 가능한 프로세스 기준선 만들기

다른 작업이 없는 상태에서 대표적인 빌드를 한 번 실행한 다음, 압축, 검증, 인덱싱을 동시에 실행하는 상태에서 같은 빌드를 반복합니다. 두 경우 모두 빌드 시간, 실패 단계, 주요 프로세스의 CPU 및 메모리 사용량, 상태, nice 값을 기록합니다.

mkdir -p "$HOME/ci-observe"

ps -axo pid,ppid,user,%cpu,%mem,state,nice,etime,command \
  | sort -k4 -nr \
  | head -n 40 \
  > "$HOME/ci-observe/processes.txt"

iostat -w 2 -c 15 > "$HOME/ci-observe/iostat.txt"
vm_stat 2 15 > "$HOME/ci-observe/vm-stat.txt"

샘플링은 실제 작업 공간과 실제 의존성 규모를 반영해야 하지만, 최초 의존성 다운로드가 포함된 빌드와 안정화된 빌드를 같은 기준선에 섞어서는 안 됩니다. 빌드 시간이 늘어나면서 iostat이 계속 바쁜 상태를 보이고 압축 프로세스가 CPU를 눈에 띄게 점유한다면 보조 작업을 조정할 근거가 있습니다. 반면 주된 문제가 메모리 압박이나 과도한 테스트 동시 실행이라면 우선순위만 바꿔서는 대개 해결되지 않습니다.

우선순위는 스케줄러에 전달하는 힌트이지 리소스 상한이 아닙니다. “누가 먼저 실행될지”를 조정하는 데는 적합하지만 동시 실행 제어를 대신할 수 없으며, 특정 작업에 고정된 CPU 비율을 보장하지도 않습니다.

핵심 경로에 따라 작업 분류하기

CI 프로세스는 세 가지 유형으로 나눌 수 있습니다. 첫 번째는 컴파일, 링크, 테스트, 산출물 내보내기입니다. 이 작업들은 파이프라인의 완료 여부를 결정하므로 정상 우선순위를 유지해야 합니다. 두 번째는 로그 압축, 체크섬 생성, 오래된 산출물 정리입니다. 반드시 완료되어야 하지만 일반적으로 빌드보다 먼저 실행될 필요는 없습니다. 세 번째는 편집기 인덱싱, 대화형 분석, 임시 진단입니다. 필요한 경우에만 시작해야 합니다.

도구 이름만으로 일괄 분류하지 않기

같은 도구라도 서로 다른 경로에 포함될 수 있습니다. 예를 들어 tar가 빌드 전에 필수 의존성을 압축 해제하는 데 사용된다면 핵심 작업이지만, 빌드 후 로그를 압축하는 데 사용된다면 백그라운드 작업입니다. 판단 기준은 다음 단계의 진행을 차단하는지, 실패 시 파이프라인을 반드시 중단해야 하는지, 출력이 현재 작업에서 즉시 사용되는지입니다.

작업 분류는 운영자가 그때그때 명령을 실행하는 방식보다 파이프라인 설정에 명시하는 것이 좋습니다. 그러면 스크립트를 검토할 때 어떤 명령의 우선순위가 낮아졌는지 바로 확인할 수 있고, 새 작업이 부적절한 정책을 기본적으로 상속하는 문제도 방지할 수 있습니다.

nice와 taskpolicy로 백그라운드 작업 감싸기

nice는 프로세스의 스케줄링 우선순위 값을 조정하며, 양수는 다른 프로세스에 실행 기회를 더 양보하겠다는 의미입니다. 일반 사용자는 자신이 시작한 프로세스의 우선순위를 낮출 수 있지만 임의로 더 높은 우선순위로 올릴 수는 없습니다. macOS의 taskpolicy -b는 명령을 백그라운드 정책으로 실행하며 CPU 이외의 영역에도 영향을 줄 수 있으므로, 핵심 경로를 차단하지 않는다고 확인된 작업에만 사용해야 합니다.

다음 스크립트는 체크섬 생성을 낮은 우선순위의 백그라운드 작업으로 실행하고 Xcode 빌드는 정상 정책으로 유지하면서, 각각의 종료 상태도 보존합니다.

#!/bin/zsh

set -u
mkdir -p Artifacts Logs

taskpolicy -b nice -n 10 /bin/sh -c \
  'find Artifacts -type f -print0 | xargs -0 shasum -a 256 > Logs/checksums.txt' &
audit_pid=$!

xcodebuild \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  build > Logs/xcodebuild.log 2>&1
build_rc=$?

wait "$audit_pid"
audit_rc=$?

if (( build_rc != 0 )); then
  exit "$build_rc"
fi

exit "$audit_rc"

CI Runner 전체에 taskpolicy -b를 일괄 적용해서는 안 됩니다. 그렇게 하면 컴파일러, 테스트 프로세스, 하위 프로세스까지 모두 낮은 우선순위로 실행되어 전체 파이프라인이 느려지지만, 어떤 작업이 원인인지는 파악하기 어려워집니다. 래퍼는 가능한 한 개별 백그라운드 명령에 가깝게 적용해야 합니다.

애플리케이션 코드에서 QoS 올바르게 사용하기

보조 작업을 자체 개발한 Swift 도구에서 실행한다면 프로세스를 시작한 뒤 역할을 추측하기보다 코드 수준에서 큐 QoS를 지정해야 합니다. 사용자가 시작하고 결과를 기다리는 작업에는 .userInitiated를 사용할 수 있습니다. 로그 정리나 캐시 점검처럼 즉시 처리할 필요가 없는 작업에는 .utility가 적합합니다. .background는 사용자가 완료를 기다리지 않고, 처리가 지연되어도 현재 결과에 영향을 주지 않는 작업에만 적합합니다.

let queue = DispatchQueue(
    label: "com.surevm.ci.artifact-audit",
    qos: .utility
)

queue.async {
    auditArtifacts()
}

“더 빠르게” 만들겠다는 이유로 모든 큐를 .userInteractive로 설정해서는 안 됩니다. 지나치게 높은 QoS를 지정하면 보조 작업이 핵심 작업과 스케줄링 리소스를 놓고 경쟁하며, 우선순위 역전이 발생할 수도 있습니다. 예를 들어 높은 우선순위의 작업이 낮은 우선순위 큐가 보유한 잠금을 기다리게 될 수 있습니다. 공유 잠금, 직렬 큐, 동기 호출도 모두 점검 대상에 포함해야 합니다.

효과 검증 및 롤백 조건 설정하기

조정 후에는 동일한 빌드 입력으로 최소 세 차례 반복 실행하고 중앙값 기준의 소요 시간, 실패 지점, 리소스 샘플을 비교해야 합니다. 한 번 빨라졌다는 사실만으로는 정책이 효과적이라고 입증할 수 없습니다. 로그 압축과 체크섬 생성 같은 백그라운드 작업이 완전하게 종료되었는지도 확인해야 하며, “핵심 빌드가 성공했다”는 이유로 보조 작업의 실패를 가려서는 안 됩니다.

검증할 때는 다음 항목을 순서대로 확인할 수 있습니다.

우선순위를 낮춘 뒤 보조 작업이 다음 빌드까지 밀려 쌓인다면 문제는 리소스 경쟁에서 처리량 부족으로 바뀐 것입니다. 이 경우 nice 값을 계속 높일 것이 아니라 백그라운드 작업 수를 줄이거나 처리 범위를 축소하고, 해당 작업을 빌드 완료 후 실행되는 별도 단계로 옮겨야 합니다. SureVM 노드에서 선택할 수 있는 구체적인 구성은 콘솔에서 확인해야 합니다. 어떤 구성을 사용하더라도 먼저 핵심 경로를 구분한 뒤 스케줄링 정책을 변경하는 방식이 전역 설정을 조정하는 것보다 일반적으로 검증과 롤백이 더 쉽습니다.

자주 묻는 질문

nice와 taskpolicy로 CPU 사용률 상한을 지정할 수 있나요?

아니요. 두 도구는 스케줄링 선호도와 백그라운드 정책을 조정할 뿐 고정 자원 한도를 만들지 않습니다. 빌드 병렬 수, 테스트 샤드, 백그라운드 작업 수도 함께 제한해야 합니다.

어떤 CI 작업을 백그라운드 정책으로 실행해야 하나요?

로그 압축, 체크섬 생성, 오래된 산출물 정리, 비차단 인덱싱이 일반적인 대상입니다. 컴파일, 링크, 테스트와 직접 의존 작업은 정상 우선순위를 유지해야 합니다.

SureVM 클라우드 Mac

빌드, 개발 및 실험을 위한 전용 물리 Mac 노드를 선택하세요

두 가지 Mac mini M4 구성, 네 가지 대여 기간, 주문 가능한 다섯 개 노드를 비교한 뒤 실제 워크플로에 맞는 구성을 선택하세요.

대여 옵션 선택