빌드 성능 분석

문제 신고 <ph type="x-smartling-placeholder"></ph> 소스 보기 1박 · 7.2 · 7.1 · 7.0 · 6.5 · 6.4

Bazel은 복잡하고 빌드 과정에서 다양한 일을 합니다. 그중 일부는 빌드 성능에 영향을 미칠 수 있습니다. 이 페이지는 빌드 성능에 미치는 영향에 대해 알아보겠습니다. 동안 빌드 성능을 감지하는 방법에 대한 몇 가지 예시를 포함했습니다. 측정항목 추출을 통한 문제 해결 문제를 해결하기 위해 무엇을 할 수 있는지 알아보겠습니다. 이를 통해 이러한 개념을 적용하여 할 수 있습니다.

클린 빌드와 증분 빌드 비교

클린 빌드는 모든 것을 처음부터 빌드하는 반면 증분식 빌드가 이미 완료된 작업을 재사용합니다.

특히 다음과 같은 경우에 클린 빌드와 증분 빌드를 별도로 확인하는 것이 좋습니다. 캠페인 상태에 따라 달라지는 측정항목을 수집 / 집계하고 Bazel의 캐시 (예: 빌드 요청 크기 측정항목 ). 또한 두 가지 서로 다른 사용자 환경을 나타냅니다. 기존 대비 처음부터 클린 빌드 (콜드 캐시로 인해 더 오래 걸림), 증분 개발자가 코드를 반복할 때 빌드가 훨씬 더 자주 발생합니다. 일반적으로 캐시가 일반적으로 이미 웜 상태이기 때문입니다.

BEP의 CumulativeMetrics.num_analyses 필드를 사용하여 살펴보겠습니다 num_analyses <= 1인 경우 클린 빌드입니다. 그 외의 경우에는 광범위하게 증분 빌드일 가능성이 높으며 사용자가 다른 플래그 또는 다른 대상에 추가하여 사실상 클린 빌드를 만듭니다. 모든 문자 성과 증분에 대한 더 엄격한 정의가 휴리스틱 처리(예: 로드된 패키지 수 확인) (PackageMetrics.packages_loaded).

빌드 성능의 프록시로서의 확정적인 빌드 측정항목

비확정성으로 인해 빌드 성능을 측정하기가 어려울 수 있습니다. 특정 측정항목 (예: Bazel의 CPU 시간 또는 원격 서버의 합니다. 따라서 결정론적 측정항목을 Bazel이 수행한 작업량에 따라 성능에 영향을 미칩니다.

빌드 요청의 크기는 빌드에 상당한 영향을 줄 수 있음 확인할 수 있습니다 빌드가 클수록 분석 및 분석 프로세스에 빌드 그래프를 구성할 수 있습니다. 빌드의 자연스러운 성장은 더 많은 종속 항목이 추가/생성되면서 복잡성이 증가함 빌드하는 데 더 많은 비용이 듭니다

이 문제를 다양한 빌드 단계로 나누어서 다음을 사용할 수 있습니다. 각 단계에서 수행되는 작업에 대한 프록시 지표로서의 지표:

  1. PackageMetrics.packages_loaded: 성공적으로 로드된 패키지 수입니다. 여기서 회귀는 읽고 파싱하기 위해 수행해야 하는 더 많은 작업을 나타냅니다. 각 추가 BUILD 파일을 빌드합니다.

    • 이는 종종 종속 항목이 추가되고 각 종속 항목을 로드해야 하기 때문에 임시 폐쇄
    • query / cquery를 사용하여 다음을 찾습니다. 여기에 새 종속 항목이 추가되었을 수 있습니다
  2. TargetMetrics.targets_configured: 타겟의 수와 관점을 보여줍니다. 회귀는 구성된 타겟 그래프를 생성하고 순회합니다.

    • 이는 종종 종속 항목이 추가되고 임시 폐쇄 그래프입니다.
    • cquery를 사용하여 새로운 종속 항목이 추가되었을 수 있습니다
  3. ActionSummary.actions_created: 빌드에서 생성된 작업을 나타냅니다. 회귀는 액션 그래프를 구성하는 데 더 많은 작업을 나타냅니다. 참고 실행되지 않았을 수 있는 사용되지 않는 작업도 포함됩니다.

  4. ActionSummary.actions_executed: 실행된 작업 수 회귀는 이러한 작업을 실행하는 데 더 많은 작업을 직접 나타냅니다.

    • BEP는 작업 통계를 작성합니다. 가장 많이 실행된 작업 유형을 보여주는 ActionData입니다. 기본적으로 상위 20개 액션 유형을 수집하지만 --experimental_record_metrics_for_all_mnemonics 드림 을 사용하여 실행된 모든 작업 유형에 관한 데이터를 수집합니다.
    • 어떤 종류의 작업이 실행되었는지 파악하는 데 도움이 됩니다. (추가로)
  5. BuildGraphSummary.outputArtifactCount: 다음에 의해 생성된 아티팩트 수입니다. 확인할 수 있습니다

    • 실행된 작업 수가 증가하지 않았다면 규칙 구현이 변경된 경우

이러한 측정항목은 모두 로컬 캐시의 상태에 영향을 받기 때문에 이러한 측정항목을 추출하는 빌드가 깨끗한 빌드

이러한 측정항목에서 회귀가 발생할 경우 실제 경과 시간, CPU 시간, 메모리 사용량의 회귀를 검출할 수 있습니다

로컬 리소스 사용

Bazel은 로컬 머신의 다양한 리소스를 빌드 그래프를 확인하고, 실행을 구동하며, 로컬 작업 실행을 위해) 작업을 수행하는 데 있어 머신의 성능 / 가용성에 영향을 줄 수 있습니다. 빌드 및 기타 작업을 할 수 있습니다.

소요 시간

노이즈에 가장 취약한 측정항목 (빌드에 따라 크게 다를 수 있음) 시간이라고 할 수 있습니다. 특히 실제 경과 시간, CPU 시간 및 시스템 시간이 있습니다. 다음과 같은 작업을 할 수 있습니다. bazel-bench를 사용하여 충분한 --runs 수를 가지고 있으면 측정의 통계적 유의성 향상

  • 실제 경과 시간은 실제 경과 시간입니다.

    • 실제 경과 시간 회귀하는 경우 JSON 트레이스 프로필 비교하세요. 그렇지 않다면 장벽에 영향을 미쳤을 수 있는 다른 회귀된 측정항목 조사 있습니다.
  • CPU 시간은 CPU에서 사용자 코드를 실행하는 데 소요된 시간입니다.

    • 두 개의 프로젝트 커밋 간에 CPU 시간이 회귀하는 경우 Starlark CPU 프로필이 있습니다 또한 --nobuild를 사용하여 빌드를 분석 단계로 제한하세요. 왜냐하면 이 단계에서 대부분의 CPU 사용량이 많습니다.
  • 시스템 시간은 커널에서 CPU가 소비한 시간입니다.

    • 시스템 시간이 회귀하는 경우 Bazel이 읽을 때 대부분 I/O와 상관관계가 있습니다. 파일을 삭제합니다.

시스템 전체 로드 프로파일링

--experimental_collect_load_average_in_profiler 드림 Bazel 6.0에 도입된 플래그가 있으므로 JSON 트레이스 프로파일러는 호출 중 시스템 부하 평균입니다.

시스템 부하 평균이 포함된 프로필

그림 1. 시스템 부하 평균이 포함된 프로필입니다.

Bazel 호출 중 부하가 높으면 Bazel 일정이 있음을 나타낼 수 있습니다. 너무 많은 로컬 작업을 동시에 실행할 수 없습니다 다음 사항도 살펴보시기 바랍니다. 조정 중 --local_cpu_resources 드림 및 --local_ram_resources, 특히 컨테이너 환경에서 (최소한 #16512가 병합됨).

Bazel 메모리 사용량 모니터링

Bazel의 메모리 사용량을 확인할 수 있는 두 가지 기본 소스인 Bazel infoBEP

  • bazel info used-heap-size-after-gc: 이후에 사용된 메모리 양(바이트) System.gc() 호출

    • Bazel 벤치 는 이 측정항목에 대한 업계 기준치도 제공합니다.
    • 또한 peak-heap-size, max-heap-size, used-heap-size도 있습니다. 및 committed-heap-size( 문서)을 참조하지만 관련성이 낮아집니다
  • BEP MemoryMetrics.peak_post_gc_heap_size: 최대 JVM 힙 크기 GC 후 바이트(바이트)(설정 필요) --memory_profile 전체 GC를 강제하려는 시도).

메모리 사용량 회귀는 일반적으로 메모리 사용량의 빌드 요청 크기 측정항목 종속 항목 추가나 규칙 변경으로 인해 발생하는 경우가 많습니다. 있습니다.

Bazel의 메모리 공간을 보다 세분화된 수준으로 분석하려면 다음을 사용하는 것이 좋습니다. 기본 제공 메모리 프로파일러 살펴보겠습니다

영구 작업자의 메모리 프로파일링

지속적 작업자를 사용하면 메모리 공간을 크게 차지할 수 있으므로 (특히 인터프리트 언어의 경우) 있습니다 Bazel은 작업자, 특히 WorkerMetrics.WorkerStats.worker_memory_in_kb 필드는 메모리 양을 알려줍니다. 사용할 수 있습니다 (니모닉에 의해).

JSON 트레이스 프로파일러도 이 메서드는 호출 중에 영구 작업자 메모리 사용량을 --experimental_collect_system_network_usage 플래그 (Bazel 6.0의 새로운 기능)입니다.

작업자 메모리 사용량이 포함된 프로필

그림 2. 작업자 메모리 사용량이 포함된 프로필입니다.

다음 값을 낮춤 --worker_max_instances 드림 (기본값 4)는 영구 작업자가 사용하는 메모리의 양입니다. Google에서는 Bazel의 리소스 관리자와 스케줄러를 더욱 스마트하게 만들어 앞으로 덜 필요할 것입니다

원격 빌드의 네트워크 트래픽 모니터링

원격 실행에서 Bazel은 HTTP(S) 배포의 결과로 빌드된 아티팩트를 실행할 수 있습니다 따라서 네트워크 대역폭은 확인할 수 있습니다

빌드에 원격 실행을 사용 중인 경우, 다음을 사용하여 호출 중에 네트워크 트래픽을 모니터링하고 BEPNetworkMetrics.SystemNetworkStats 프로토콜 (--experimental_collect_system_network_usage를 전달해야 함)

또한 JSON 트레이스 프로필 빌드 과정 전반에 걸친 시스템 전체의 네트워크 사용량을 볼 수 있음 --experimental_collect_system_network_usage 플래그 (Bazel의 새로운 기능)를 전달하여 버전 6.0).

시스템 전체 네트워크 사용량이 포함된 프로필

그림 3. 시스템 전체 네트워크 사용량이 포함된 프로필입니다.

원격 실행을 사용할 때 네트워크 사용량이 높지만 다소 평평하다는 것은 네트워크가 빌드의 병목 현상입니다. 아직 사용하지 않는다면 다음을 전달하여 바이트 없이 빌드를 사용 설정하고, --remote_download_minimal 이렇게 하면 불필요한 중간 아티팩트의 다운로드를 방지하여 빌드 속도를 높일 수 있습니다.

또 다른 옵션은 저장할 디스크 캐시 다운로드 대역폭