스카이프레임

문제 신고 소스 보기 1박 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel의 병렬 평가 및 성과 증분 모델

데이터 모델

데이터 모델은 다음 항목으로 구성됩니다.

  • SkyValue 노드라고도 합니다. SkyValues는 변경할 수 없는 객체로, 빌드 과정에서 빌드된 모든 데이터와 지정할 수도 있습니다 예: 입력 파일, 출력 파일, 대상, 구성 있습니다
  • SkyKey SkyValue를 참조할 수 있는 변경 불가능한 짧은 이름입니다. 예를 들면 다음과 같습니다. FILECONTENTS:/tmp/foo 또는 PACKAGE://foo입니다.
  • SkyFunction 키와 종속 노드를 기반으로 노드를 빌드합니다.
  • 노드 그래프 종속 항목 관계를 포함하는 데이터 구조 노드라는 두 가지 리소스가 있습니다
  • Skyframe 증분 평가 프레임워크 Bazel의 코드명: 기반으로 합니다.

평가

빌드는 빌드 요청을 나타내는 노드를 평가하여 이루어집니다.

먼저 Bazel은 최상위 수준의 키에 해당하는 SkyFunction를 찾습니다. SkyKey입니다. 그런 다음 필요한 노드의 평가를 요청합니다. 최상위 노드를 평가하고 결과적으로 다른 SkyFunction 호출을 발생시킵니다. 리프 노드에 연결될 때까지 유지되지 않습니다 리프 노드는 일반적으로 입력 파일이 있습니다 마지막으로 Bazel은 최상위 SkyValue, 일부 부작용 (예: 파일의 출력 파일) 노드 간 종속성의 방향성 비순환 그래프(DAG)를 빌드에 관여합니다

SkyFunction는 알 수 없는 경우 여러 패스에서 SkyKeys를 요청할 수 있습니다. 작업을 수행하는 데 필요한 모든 노드를 진행합니다. 간단한 예는 심볼릭 링크로 밝혀지는 입력 파일 노드: 함수는 심볼릭 링크임을 인식하여 파일 시스템 노드를 심볼릭 링크의 대상을 나타냅니다. 그러나 그것 자체가 심볼릭 링크일 수 있습니다. 이 경우 원래 함수가 타겟도 가져와야 합니다.

함수는 코드에서 SkyFunction 인터페이스로 표현됩니다. 제공되는 서비스에만 적용됩니다.SkyFunction.Environment 이러한 함수에서 할 수 있는 작업은 다음과 같습니다.

  • env.getValue 호출을 통해 다른 노드의 평가를 요청합니다. 만약 노드를 사용할 수 있으면 값이 반환되고, 그렇지 않으면 null가 반환됩니다. 함수 자체는 null를 반환해야 합니다. 후자의 경우 종속 노드가 평가된 후 원래 노드 빌더가 다시 호출되지만 이번에는 동일한 env.getValue 호출이 null가 아닌 값을 사용합니다.
  • env.getValues()를 호출하여 다른 여러 노드의 평가를 요청합니다. 이 작업은 종속 노드가 있습니다
  • 호출 중에 계산 수행
  • 파일 시스템에 파일 쓰기와 같은 부작용이 발생합니다. 돌봄 필요 두 개의 다른 기능이 발가락과 발가락이 있습니다. 일반적으로 부작용을 작성합니다 (데이터가 Bazel에서 외부로 흐르는 경우). 부작용 (데이터가 Bazel로 흐르며 등록된 종속 항목)이 등록되지 않은 종속 항목이므로 이로 인해 잘못된 증분 빌드가 발생할 수 있습니다.

올바르게 작동하는 SkyFunction 구현은 다른 방식으로 데이터에 액세스하지 않음 종속 항목을 요청하는 것보다 더 나은 결과를 얻기 위해 Bazel이 파일에 데이터 종속 항목을 등록하지 않으므로 그 결과 잘못된 증분 빌드가 발생했습니다.

함수가 작업을 실행하기에 충분한 데이터를 확보하면 null가 아닌 값을 반환해야 합니다. 완료를 나타내는 값입니다.

이 평가 전략은 다음과 같은 여러 이점이 있습니다.

  • 밀폐성. 함수가 Bazel은 입력 상태가 동일하면 동일한 데이터가 반환됩니다. 모든 스카이 함수가 확정적인 경우에는 전체 빌드도 확정적입니다
  • 정확하고 완벽한 성과 증분. 모든 함수의 모든 입력 데이터가 기록되면 Bazel은 모든 노드가 기록되어야 하는 정확한 노드 집합만 무효화됩니다
  • 동시 로드 개수 함수는 특정 CPU와 GPU를 통해서만 종속 항목을 요청하지 않는 경우 서로 종속되지 않는 함수가 Bazel은 Bazel이 코드를 실행하는 동안과 동일한 결과를 순차적으로 실행되었습니다

성과 증분

함수는 다른 노드에 의존해야만 입력 데이터에 액세스할 수 있으므로 Bazel은 입력 파일에서 출력까지의 전체 데이터 흐름 그래프를 이 정보를 사용하여 실제로 필요한 노드만 변경된 입력 파일 집합의 역전이적 종료

특히, 가능한 두 가지 성과 증분 전략이 있습니다. 바로 상향식 전략입니다. 다른 하나는 하향식입니다. 다음 중 종속 항목 그래프에서 올바른 것은 보이게 됩니다.

  • 상향식 무효화 중 그래프가 빌드되고 데이터 집합이 변경된 후 입력에 전이하여 종속되는 모든 노드가 무효화됩니다. 변경할 수 있습니다. 이는 동일한 최상위 노드가 빌드되는 경우에 가장 적합합니다. 다시 시도합니다. 상향식 무효화를 사용하려면 모든 항목에서 stat()를 실행해야 합니다. 이전 빌드의 입력 파일을 가져와서 변경되었는지 확인합니다. 이 inotify 또는 유사한 메커니즘을 사용하여 개선할 수 있음 변경할 수 있습니다.

  • 하향식 무효화 중 최상위 노드의 전이적 클로저 가 선택되고 과도적 클로저가 깨끗한 노드만 유지됩니다. 이것은 노드 그래프가 크면 더 낫지만, 다음 빌드에는 작은 부분집합: 상향식 무효화는 큰 그래프를 무효화함 첫 번째 빌드의 작은 부분만 이동하는 하향식 무효화와는 달리 두 번째 빌드의 그래프입니다.

Bazel은 상향식 무효화만 실행합니다.

성과 증분을 더 높이기 위해 Bazel은 변경 프루닝을 사용합니다. 무효화되었지만 다시 빌드하면 새 값이 동일한 이 노드의 변경으로 인해 무효화된 노드를 "부활"했다고 합니다.

이 방법은 예를 들어 C++ 파일의 주석을 변경하는 경우 유용합니다. 여기서 생성된 .o 파일은 동일하므로 호출할 필요가 없습니다. 다시 호출할 수 있습니다

증분 연결 / 컴파일

이 모델의 주요 단점은 노드 무효화가 '모 아니면 도' 문제: 종속 항목이 변경될 때 종속 노드는 항상 처음부터 다시 빌드(변경할 수 있는 더 나은 알고리즘이 있더라도) 노드의 이전 값을 업데이트합니다. 이렇게 하면 유용하게 활용할 수 있습니다.

  • 증분 연결
  • JAR 파일에서 단일 클래스 파일이 변경되면 JAR 파일을 처음부터 다시 빌드하는 대신 그 자리에서 수정할 수 있습니다.

Bazel이 원칙적인 방식으로 이러한 항목을 지원하지 않는 이유 두 가지입니다.

  • 실적 향상은 제한적이었습니다.
  • 변형의 결과가 그 결과와 동일한지 검증하기 어려움 Google은 비트 대 비트 단위 빌드를 중시합니다. 반복 가능합니다

지금까지는 단일 계층 구조를 분해하여 이러한 방식으로 부분적 재평가를 달성할 수 있습니다. 예를 들어 Android 앱에서는 모든 클래스를 여러 그룹과 dex로 분할할 수 있습니다. 분리하는 것이 좋습니다 이렇게 하면 그룹의 클래스가 변경되지 않은 경우 덱싱이 다시 실행할 필요가 없습니다

Bazel 개념에 매핑

SkyFunctionSkyValue 키에 대한 대략적인 요약입니다. Bazel이 빌드를 수행하는 데 사용하는 구현을 보여줍니다.

  • FileStateValue와 같습니다. lstat()의 결과입니다. 기존 파일의 경우 함수는 또한 추가 정보를 계산하여 있습니다. 이는 스카이프레임 그래프에서 최하위 노드이며 종속 항목이 포함됩니다
  • FileValue를 사용하여 파일 값을 확인할 수 있습니다. 실제 콘텐츠 또는 파일의 확인된 경로입니다. 상응하는 FileStateValue 및 해결해야 하는 심볼릭 링크 (예: a/bFileValue) 에는 a의 확인된 경로와 a/b의 확인된 경로가 필요합니다. 이 FileValueFileStateValue를 구별하는 것이 중요합니다. 후자는 파일의 콘텐츠가 필요하지 않은 경우에 사용할 수 있습니다. 확인할 수 있습니다 예를 들어 파일 콘텐츠는 파일 시스템 glob (예: srcs=glob(["*/*.java"])) 평가
  • DirectoryListingStateValue를 참조하세요. readdir()의 결과입니다. 좋아요 FileStateValue: 가장 낮은 수준의 노드이며 종속 항목이 없습니다.
  • DirectoryListingValue를 참조하세요. 이 디렉터리를 의미합니다 상응하는 DirectoryListingStateValue에 종속됩니다. 디렉터리의 관련 FileValue도 확인할 수 있습니다.
  • PackageValue의 인스턴스입니다. BUILD 파일의 파싱된 버전을 나타냅니다. 기준 관련 BUILD 파일의 FileValue 및 전이적 패키지의 glob 확인에 사용되는 DirectoryListingValue (내부적으로 BUILD 파일의 콘텐츠를 나타내는 데이터 구조)
  • ConfiguredTargetValue를 사용합니다. 튜플인 구성된 타겟을 나타냅니다. 표적을 분석하는 동안 생성되는 일련의 행동과 종속된 구성된 대상에 제공된 정보 상응하는 타겟이 있는 PackageValue, ConfiguredTargetValues 직접 종속 항목 및 빌드를 나타내는 특수 노드로 구성됩니다. 구성할 수 있습니다
  • ArtifactValue로 표현됩니다. 빌드의 파일(소스 또는 출력 아티팩트를 생성합니다. 아티팩트는 파일과 거의 동일하며 파일을 참조할 수 있습니다. 소스 파일 연결된 노드의 FileValue 및 출력 아티팩트에 종속됩니다. 디코더를 생성하는 작업의 ActionExecutionValue에 합니다.
  • ActionExecutionValue로 변경되었습니다. 작업의 실행을 나타냅니다. 기준 입력 파일의 ArtifactValues입니다. 실행하는 작업이 포함됩니다. 이는 SkyKeys가 암호화되어야 한다는 개념과 있습니다. 다음과 같은 경우 ActionExecutionValueArtifactValue가 사용되지 않습니다. 실행 단계가 실행되지 않습니다

시각적 보조 자료로 이 다이어그램은 Bazel 자체 빌드 후 SkyFunction 구현은 다음을 충족해야 합니다.

SkyFunction 구현 관계 그래프