Skyframe là trái tim của Bazel, hệ thống xây dựng mã nguồn mở, giúp nó đạt được tốc độ và độ tin cậy. Để hiểu rõ hơn về Skyframe, chúng ta cần khám phá mô hình dữ liệu mà nó sử dụng, đặc biệt là Mối Quan Hệ Giữa Thông Tin Và Dữ Liệu.
Mô hình Dữ liệu của Skyframe
Mô hình dữ liệu trong Skyframe bao gồm các thành phần then chốt sau:
- SkyValue (Nút): Đây là đơn vị dữ liệu cơ bản, bất biến, chứa toàn bộ thông tin được tạo ra trong quá trình xây dựng. Ví dụ về
SkyValue
bao gồm tệp đầu vào, tệp đầu ra, mục tiêu xây dựng và mục tiêu đã định cấu hình. - SkyKey: Một định danh ngắn gọn, bất biến để tham chiếu đến một
SkyValue
cụ thể. Ví dụ:FILECONTENTS:/tmp/foo
hoặcPACKAGE://foo
.SkyKey
chính là chìa khóa để truy xuất thông tin từSkyValue
. - SkyFunction: Một hàm chịu trách nhiệm tạo ra các
SkyValue
dựa trênSkyKey
và cácSkyValue
phụ thuộc khác. - Biểu đồ Nút: Một cấu trúc dữ liệu lưu trữ mối quan hệ phụ thuộc giữa các
SkyValue
. Đây là bản đồ chi tiết về luồng thông tin trong quá trình xây dựng. - Skyframe: Tên gọi cho khung đánh giá tăng dần mà Bazel sử dụng để quản lý quá trình xây dựng.
Đánh giá trong Skyframe: Chuyển Đổi Dữ Liệu Thành Thông Tin
Quá trình xây dựng trong Bazel được thực hiện thông qua việc “đánh giá” các nút, bắt đầu từ nút đại diện cho yêu cầu xây dựng cấp cao nhất.
- Tìm SkyFunction: Bazel xác định
SkyFunction
tương ứng vớiSkyKey
của nút cấp cao nhất. - Yêu Cầu Đánh Giá:
SkyFunction
này yêu cầu đánh giá các nút phụ thuộc cần thiết để tạo ra nút cấp cao nhất. Quá trình này lặp lại, tạo ra một chuỗi các lệnh gọiSkyFunction
cho đến khi đạt đến các nút lá (thường là các nút đại diện cho tệp đầu vào). - Xây Dựng Biểu Đồ Phụ Thuộc: Trong quá trình đánh giá, Bazel xây dựng một biểu đồ có hướng (DAG) thể hiện các mối quan hệ phụ thuộc giữa các nút liên quan đến bản dựng.
- Kết Quả: Cuối cùng, Bazel thu được giá trị của
SkyValue
cấp cao nhất, tạo ra các tác động phụ (ví dụ: tệp đầu ra) và hoàn thiện biểu đồ phụ thuộc.
SkyFunction
đóng vai trò trung tâm trong việc chuyển đổi dữ liệu thô (ví dụ: nội dung tệp) thành thông tin có ý nghĩa (ví dụ: mục tiêu đã biên dịch).
Một SkyFunction
có thể yêu cầu nhiều lượt đánh giá nếu không phải tất cả các nút phụ thuộc đều được biết trước. Ví dụ, nếu một tệp đầu vào là một liên kết tượng trưng, SkyFunction
cần phải xác định mục tiêu của liên kết và truy xuất thông tin về mục tiêu đó.
Các hàm SkyFunction
tương tác với môi trường thông qua giao diện SkyFunction.Environment
. Các hàm này có thể:
- Yêu cầu đánh giá các nút khác bằng cách gọi
env.getValue
hoặcenv.getValues
(đánh giá song song). - Thực hiện các phép tính cần thiết.
- Tạo ra các tác động phụ (ví dụ: ghi tệp), nhưng cần cẩn trọng để tránh xung đột giữa các hàm.
Sơ đồ mô tả các mối quan hệ giữa các triển khai SkyFunction khác nhau sau khi tạo bản dựng bằng Bazel. Chú thích các thành phần chính như FileStateValue, FileValue, DirectoryListingStateValue, PackageValue, ConfiguredTargetValue, ArtifactValue và ActionExecutionValue, thể hiện cách chúng tương tác và phụ thuộc lẫn nhau trong quá trình xây dựng.
Các Lợi Ích của Skyframe: Độ Tin Cậy và Hiệu Suất
Chiến lược đánh giá của Skyframe mang lại nhiều lợi ích quan trọng:
- Độ kín: Nếu các hàm chỉ truy cập dữ liệu thông qua các nút phụ thuộc, Bazel đảm bảo rằng trạng thái đầu vào giống nhau sẽ luôn tạo ra kết quả giống nhau. Điều này đảm bảo tính xác định của bản dựng.
- Tính tăng dần chính xác: Bazel theo dõi tất cả các phụ thuộc dữ liệu của hàm, cho phép vô hiệu hóa chính xác các nút cần thiết khi đầu vào thay đổi.
- Tính song song: Các hàm không phụ thuộc lẫn nhau có thể chạy song song, tăng tốc quá trình xây dựng.
Tính Tăng Dần: Tối Ưu Hóa Việc Sử Dụng Thông Tin
Skyframe sử dụng biểu đồ luồng dữ liệu để chỉ tạo lại các nút thực sự cần thiết, dựa trên các thay đổi ở đầu vào. Có hai chiến lược tăng dần tiềm năng: từ dưới lên và từ trên xuống. Bazel hiện chỉ sử dụng chiến lược từ dưới lên.
Để tối ưu hóa hơn nữa, Bazel sử dụng tính năng loại bỏ thay đổi: nếu một nút bị vô hiệu hóa, nhưng giá trị mới của nó giống với giá trị cũ, các nút phụ thuộc được “hồi sinh”. Điều này đặc biệt hữu ích trong các trường hợp như thay đổi nhận xét trong mã nguồn, nơi tệp đối tượng biên dịch có thể không thay đổi.
Liên Kết và Biên Dịch Gia Tăng: Đánh Đổi Hiệu Suất và Độ Tin Cậy
Mặc dù có những lợi ích tiềm năng, Skyframe không hỗ trợ các kỹ thuật như liên kết gia tăng hoặc cập nhật JAR tại chỗ khi chỉ một tệp lớp thay đổi. Điều này là do việc xác minh tính chính xác của các bản dựng gia tăng phức tạp rất khó khăn, và Google ưu tiên các bản dựng có thể lặp lại từng bit. Thay vào đó, Bazel khuyến khích phân tích các bước xây dựng tốn kém thành các phần nhỏ hơn để tăng tính tăng dần.
Liên Kết với Các Khái Niệm của Bazel: Ánh Xạ Dữ Liệu Vào Thực Tế
Để hiểu rõ hơn về cách Skyframe hoạt động trong thực tế, hãy xem xét một số triển khai SkyFunction
và SkyValue
chính:
- FileStateValue: Kết quả của
lstat()
, cung cấp thông tin trạng thái tệp. - FileValue: Cung cấp nội dung và đường dẫn đã phân giải của một tệp, phụ thuộc vào
FileStateValue
và các liên kết tượng trưng liên quan. - DirectoryListingStateValue: Kết quả của
readdir()
, cung cấp thông tin về các mục nhập thư mục. - DirectoryListingValue: Cung cấp danh sách các mục nhập thư mục, phụ thuộc vào
DirectoryListingStateValue
vàFileValue
của thư mục. - PackageValue: Biểu diễn phiên bản đã phân tích cú pháp của tệp BUILD, phụ thuộc vào
FileValue
của tệp BUILD và cácDirectoryListingValue
liên quan đến các glob. - ConfiguredTargetValue: Biểu diễn một mục tiêu đã định cấu hình, bao gồm các hành động được tạo ra trong quá trình phân tích và thông tin cho các mục tiêu phụ thuộc.
- ArtifactValue: Biểu diễn một tệp trong bản dựng, phụ thuộc vào
FileValue
(cho tệp nguồn) hoặcActionExecutionValue
(cho cấu phần phần mềm đầu ra). - ActionExecutionValue: Biểu diễn việc thực thi một hành động, phụ thuộc vào các
ArtifactValue
của các tệp đầu vào.
Kết Luận: Skyframe và Mối Quan Hệ Giữa Thông Tin và Dữ Liệu
Skyframe là một hệ thống phức tạp nhưng mạnh mẽ, dựa trên mối quan hệ chặt chẽ giữa thông tin và dữ liệu. Dữ liệu thô (ví dụ: nội dung tệp, cấu trúc thư mục) được biểu diễn bằng các SkyValue
. Thông tin có ý nghĩa (ví dụ: mục tiêu đã biên dịch, phụ thuộc) được tạo ra thông qua các SkyFunction
bằng cách xử lý và kết hợp dữ liệu từ các SkyValue
phụ thuộc. Bằng cách quản lý các mối quan hệ này một cách hiệu quả, Skyframe cho phép Bazel thực hiện các bản dựng nhanh chóng, đáng tin cậy và có thể lặp lại. Việc hiểu rõ về mô hình dữ liệu và các nguyên tắc hoạt động của Skyframe là chìa khóa để khai thác tối đa sức mạnh của Bazel.