날짜 비워 두기: BazelCon 2023이 10월 24~25일에 Google 뮌헨에서 열립니다. 등록이 시작되었습니다. 자세히 알아보기

원격 실행을 위한 원격 캐시 적중 디버깅

문제 신고 소스 보기

이 페이지에서는 캐시 적중률을 확인하는 방법과 원격 실행 컨텍스트에서 캐시 부적중을 조사하는 방법을 설명합니다.

이 페이지에서는 원격 실행을 성공적으로 활용하는 빌드 또는 테스트가 있고 원격 캐시를 효과적으로 활용하고 있는지 확인하려고 합니다.

캐시 적중률 확인

Bazel 실행의 표준 출력에서 Bazel 작업과 대략 일치하는 프로세스를 나열하는 INFO 줄을 확인합니다. 작업이 실행된 줄의 세부정보입니다. 원격으로 실행되는 작업을 나타내는 remote 라벨, 로컬 샌드박스에서 실행되는 작업의 경우 linux-sandbox, 기타 실행 전략을 위한 기타 값을 찾아보세요. 결과가 원격 캐시에서 발생한 작업은 remote cache hit로 표시됩니다.

예를 들면 다음과 같습니다.

INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.

이 예시에는 6개의 원격 캐시 적중이 있으며 2개의 작업은 캐시 적중이 없으므로 원격으로 실행되었습니다. 내부의 세 부분은 무시할 수 있습니다. 일반적으로 기호화된 링크 생성과 같은 작은 내부 작업입니다. 로컬 캐시 적중은 이 요약에 포함되지 않습니다. 프로세스가 0개(또는 예상보다 적은 수)가 발생하면 bazel clean를 실행하고 빌드/테스트 명령어를 실행합니다.

캐시 적중 문제 해결

캐시 적중률이 예상과 다른 경우 다음을 수행합니다.

동일한 빌드/테스트 명령어를 다시 실행하면 캐시 적중이 발생하는지 확인합니다.

  1. 캐시를 채울 것으로 예상되는 빌드 또는 테스트를 실행합니다. 특정 스택에서 새 빌드를 처음 실행할 때는 원격 캐시 적중이 없을 수 있습니다. 원격 실행의 일부로 작업 결과가 캐시에 저장되며 후속 실행 시 이를 선택합니다.

  2. bazel clean를 실행합니다. 이 명령어는 로컬 캐시를 삭제하므로 로컬 캐시 적중에 의해 결과가 마스킹되지 않고 원격 캐시 적중을 조사할 수 있습니다.

  3. 조사 중인 빌드와 테스트를 같은 머신에서 다시 실행합니다.

  4. 캐시 적중률은 INFO 줄을 확인하세요. remote cache hitinternal 이외의 프로세스가 표시되지 않으면 캐시가 올바르게 채워지고 액세스되고 있는 것입니다. 이 경우 다음 섹션으로 건너뛰세요.

  5. 불일치가 발생할 수 있는 원인은 빌드에서 밀폐되지 않은 작업으로, 작업이 두 실행에서 서로 다른 작업 키를 수신하도록 합니다. 이러한 작업을 찾으려면 다음 단계를 따르세요.

    a. 문제가 되는 빌드 또는 테스트를 다시 실행하여 실행 로그를 가져옵니다.

      bazel clean
      bazel --optional-flags build //your:target --execution_log_binary_file=/tmp/exec1.log
    

    b. 두 실행 간의 실행 로그를 비교합니다. 작업이 두 로그 파일에서 동일한지 확인합니다. 불일치는 실행 사이에 발생한 변화에 대한 단서를 제공합니다. 이러한 불일치를 없애려면 빌드를 업데이트하세요.

    캐싱 문제를 해결할 수 있고 이제 반복 실행으로 모든 캐시 적중이 발생하면 다음 섹션으로 건너뛰세요.

    작업 ID는 동일하지만 캐시 적중이 없는 경우 구성에 항목이 있어 캐싱이 차단되는 것입니다. 이 섹션으로 계속 진행하여 일반적인 문제를 확인하세요.

    실행 로그를 비교할 필요가 없는 경우 사람이 읽을 수 있는 --execution_log_json_file 플래그를 대신 사용할 수 있습니다. 실행 시간이 포함되어 있고 순서를 보장하지 않으므로 안정적인 diff에 사용할 수 없습니다.

  6. 실행 로그의 모든 작업에 cacheable가 true로 설정되어 있는지 확인합니다. cacheable가 주어진 작업의 실행 로그에 표시되지 않으면 관련 규칙의 BUILD 파일 정의에 no-cache 태그가 있을 수 있다는 의미입니다. 실행 로그에서 사람이 읽을 수 있는 progress_message 필드를 보면 작업의 출처를 파악할 수 있습니다.

  7. 작업이 동일하고 cacheable이지만 캐시 적중이 없는 경우 명령줄에 빌드의 캐시 조회를 사용 중지하는 --noremote_accept_cached가 포함될 수 있습니다.

    실제 명령줄을 파악하는 것이 어렵다면 다음과 같이 빌드 이벤트 프로토콜의 표준 명령줄을 사용합니다.

    a. 텍스트의 로그 버전을 얻으려면 Bazel 명령어에 --build_event_text_file=/tmp/bep.txt를 추가하세요.

    b. 텍스트 버전의 로그를 열고 command_line_label: "canonical"structured_command_line 메시지를 검색합니다. 확장 후 모든 옵션이 표시됩니다.

    c. remote_accept_cached를 검색하고 false로 설정되어 있는지 확인합니다.

    d. remote_accept_cachedfalse이면 명령줄 또는 bazelrc 파일에서 false로 설정되어 있는 위치를 확인합니다.

머신 간 캐싱 보장

동일한 시스템에서 캐시 적중이 예상대로 발생하면 다른 머신에서 동일한 빌드/테스트를 실행합니다. 머신 간에 캐싱이 진행되지 않는다고 생각되면 다음 단계를 따르세요.

  1. 기존 캐시에 닿지 않도록 빌드를 약간 수정합니다.

  2. 첫 번째 머신에서 빌드를 실행합니다.

     bazel clean
     bazel ... build ... --execution_log_binary_file=/tmp/exec1.log
    
  3. 두 번째 머신에서 빌드를 실행하여 1단계의 수정 사항을 포함합니다.

     bazel clean
     bazel ... build ... --execution_log_binary_file=/tmp/exec2.log
    
  4. 두 실행의 실행 로그를 비교합니다. 로그가 동일하지 않으면 빌드 구성의 불일치뿐만 아니라 두 빌드 중 하나에 누출된 호스트 환경의 속성이 있는지 조사합니다.

실행 로그 비교

실행 로그에는 빌드 중에 실행된 모든 작업의 레코드가 포함됩니다. 각 작업에는 작업 키의 모든 정보가 포함된 SpawnExec 요소가 있습니다. 따라서 로그가 동일하다면 작업 캐시 키도 마찬가지입니다.

캐시 적중이 예상대로 공유되지 않는 두 빌드의 로그를 비교하려면 다음을 수행합니다.

  1. 각 빌드에서 실행 로그를 가져와 /tmp/exec1.log/tmp/exec2.log로 저장합니다.

  2. Bazel 소스 코드를 다운로드하고 아래 명령어를 사용하여 Bazel 폴더로 이동합니다. execlog 파서로 실행 로그를 파싱하려면 소스 코드가 필요합니다.

    git clone https://github.com/bazelbuild/bazel.git
    cd bazel
    
  3. 실행 로그 파서를 사용하여 로그를 텍스트로 변환합니다. 또한 다음 호출은 쉽게 비교할 수 있도록 두 번째 로그의 작업을 첫 번째 로그의 작업 순서와 일치하도록 정렬합니다.

    bazel build src/tools/execlog:parser
    bazel-bin/src/tools/execlog/parser \
      --log_path=/tmp/exec1.log \
      --log_path=/tmp/exec2.log \
      --output_path=/tmp/exec1.log.txt \
      --output_path=/tmp/exec2.log.txt
    
  4. 선호하는 텍스트를 diff /tmp/exec1.log.txt/tmp/exec2.log.txt와 다르게 사용하세요.