Bazel rất phức tạp và thực hiện nhiều việc trong quá trình tạo bản dựng, một số việc có thể ảnh hưởng đến hiệu suất bản dựng. Trang này cố gắng liên kết một số khái niệm Bazel này với những tác động của chúng đối với hiệu suất bản dựng. Mặc dù không đầy đủ, nhưng chúng tôi đã đính kèm một số ví dụ về cách phát hiện vấn đề về hiệu suất bản dựng thông qua trích xuất các chỉ số và những việc bạn có thể làm để khắc phục các vấn đề đó. Với những thông tin này, chúng tôi hy vọng bạn có thể áp dụng các khái niệm này khi điều tra sự hồi quy về hiệu suất bản dựng.
Bản dựng sạch so với bản dựng tăng dần
Bản dựng sạch là bản dựng tạo mọi thứ từ đầu, trong khi bản dựng gia tăng sử dụng lại một số công việc đã hoàn tất.
Bạn nên xem xét riêng các bản dựng sạch và bản dựng tăng dần, đặc biệt là khi bạn thu thập / tổng hợp các chỉ số phụ thuộc vào trạng thái của bộ nhớ đệm Bazel (ví dụ: chỉ số kích thước yêu cầu bản dựng). Các bản dựng này cũng đại diện cho hai trải nghiệm người dùng khác nhau. So với việc bắt đầu một bản dựng sạch từ đầu (mất nhiều thời gian hơn do bộ nhớ đệm nguội), các bản dựng gia tăng xảy ra thường xuyên hơn nhiều khi các nhà phát triển lặp lại mã (thường nhanh hơn vì bộ nhớ đệm thường đã ấm).
Bạn có thể sử dụng trường CumulativeMetrics.num_analyses
trong BEP để phân loại bản dựng. Nếu là num_analyses <= 1
, thì đó là bản dựng sạch; nếu không, chúng ta có thể phân loại rộng rãi bản dựng đó có thể là bản dựng gia tăng – người dùng có thể đã chuyển sang các cờ hoặc mục tiêu khác nhau dẫn đến bản dựng sạch hiệu quả. Mọi định nghĩa nghiêm ngặt hơn về tính gia tăng có thể sẽ phải ở dạng phỏng đoán, ví dụ: xem xét số lượng gói đã tải (PackageMetrics.packages_loaded
).
Các chỉ số bản dựng xác định là chỉ số đại diện cho hiệu suất bản dựng
Việc đo lường hiệu suất bản dựng có thể gặp khó khăn do bản chất không xác định của một số chỉ số nhất định (ví dụ: thời gian CPU hoặc thời gian xếp hàng của Bazel trên một cụm từ xa). Do đó, bạn có thể sử dụng các chỉ số xác định để làm proxy cho lượng công việc mà Bazel thực hiện, từ đó ảnh hưởng đến hiệu suất của Bazel.
Kích thước của yêu cầu bản dựng có thể ảnh hưởng đáng kể đến hiệu suất bản dựng. Một bản dựng lớn hơn có thể đại diện cho nhiều công việc hơn trong việc phân tích và tạo biểu đồ bản dựng. Sự phát triển tự nhiên của các bản dựng đi kèm với quá trình phát triển, vì nhiều phần phụ thuộc được thêm/tạo, do đó, độ phức tạp tăng lên và chi phí xây dựng tăng lên.
Chúng ta có thể chia vấn đề này thành nhiều giai đoạn xây dựng và sử dụng các chỉ số sau đây làm chỉ số proxy cho công việc ở mỗi giai đoạn:
PackageMetrics.packages_loaded
: số lượng gói đã tải thành công. Một hồi quy ở đây thể hiện nhiều công việc cần làm hơn để đọc và phân tích cú pháp từng tệp BUILD bổ sung trong giai đoạn tải.TargetMetrics.targets_configured
: biểu thị số lượng mục tiêu và khía cạnh được định cấu hình trong bản dựng. Phương pháp hồi quy thể hiện nhiều công việc hơn trong việc tạo và duyệt qua biểu đồ mục tiêu đã định cấu hình.- Điều này thường là do việc thêm các phần phụ thuộc và phải tạo biểu đồ của phép đóng bắc cầu.
- Sử dụng cquery để tìm nơi có thể đã thêm các phần phụ thuộc mới.
ActionSummary.actions_created
: đại diện cho các hành động được tạo trong bản dựng và hồi quy đại diện cho nhiều công việc hơn trong việc tạo biểu đồ hành động. Xin lưu ý rằng số liệu này cũng bao gồm các hành động không sử dụng có thể chưa được thực thi.- Sử dụng aquery để gỡ lỗi hồi quy; bạn nên bắt đầu với
--output=summary
trước khi đi sâu hơn với--skyframe_state
.
- Sử dụng aquery để gỡ lỗi hồi quy; bạn nên bắt đầu với
ActionSummary.actions_executed
: số lượng thao tác được thực thi, hồi quy trực tiếp thể hiện lượng công việc cần làm trong việc thực thi các thao tác này.- BEP ghi lại số liệu thống kê về hành động
ActionData
cho biết các loại hành động được thực thi nhiều nhất. Theo mặc định, tính năng này thu thập 20 loại hành động hàng đầu, nhưng bạn có thể truyền vào--experimental_record_metrics_for_all_mnemonics
để thu thập dữ liệu này cho tất cả các loại hành động đã được thực thi. - Điều này sẽ giúp bạn xác định những loại hành động đã được thực thi (bổ sung).
- BEP ghi lại số liệu thống kê về hành động
BuildGraphSummary.outputArtifactCount
: số lượng cấu phần phần mềm do các hành động được thực thi tạo ra.- Nếu số lượng thao tác được thực thi không tăng, thì có thể phương thức triển khai quy tắc đã được thay đổi.
Các chỉ số này đều chịu ảnh hưởng của trạng thái bộ nhớ đệm cục bộ, do đó, bạn nên đảm bảo rằng các bản dựng mà bạn trích xuất các chỉ số này là các bản dựng sạch.
Chúng tôi nhận thấy rằng sự hồi quy trong bất kỳ chỉ số nào trong số này có thể đi kèm với sự hồi quy về thời gian thực, thời gian CPU và mức sử dụng bộ nhớ.
Sử dụng tài nguyên cục bộ
Bazel sử dụng nhiều tài nguyên trên máy cục bộ của bạn (cả để phân tích biểu đồ bản dựng và thúc đẩy quá trình thực thi cũng như để chạy các thao tác cục bộ). Điều này có thể ảnh hưởng đến hiệu suất / khả năng sử dụng máy của bạn trong quá trình thực hiện bản dựng cũng như các tác vụ khác.
Thời gian đã đi
Có lẽ chỉ số dễ bị nhiễu nhất (và có thể thay đổi đáng kể giữa các bản dựng) là thời gian; cụ thể là thời gian thực, thời gian CPU và thời gian hệ thống. Bạn có thể sử dụng bazel-bench để lấy điểm chuẩn cho các chỉ số này và với số lượng --runs
đủ lớn, bạn có thể tăng mức độ ý nghĩa thống kê của phép đo.
Thời gian thực là thời gian thực tế đã trôi qua.
- Nếu chỉ thời gian thực tế bị hồi quy, bạn nên thu thập hồ sơ theo dõi JSON và tìm sự khác biệt. Nếu không, bạn nên điều tra các chỉ số hồi quy khác vì chúng có thể ảnh hưởng đến thời gian thực.
Thời gian CPU là thời gian CPU thực thi mã của người dùng.
- Nếu thời gian CPU hồi quy trên hai lần cam kết dự án, bạn nên thu thập hồ sơ CPU Starlark. Bạn cũng nên sử dụng
--nobuild
để hạn chế bản dựng ở giai đoạn phân tích vì đó là nơi thực hiện hầu hết các tác vụ nặng của CPU.
- Nếu thời gian CPU hồi quy trên hai lần cam kết dự án, bạn nên thu thập hồ sơ CPU Starlark. Bạn cũng nên sử dụng
Thời gian hệ thống là thời gian mà CPU sử dụng trong nhân.
- Nếu thời gian hệ thống hồi quy, thì thời gian này chủ yếu liên quan đến I/O khi Bazel đọc các tệp từ hệ thống tệp của bạn.
Lập hồ sơ tải trên toàn hệ thống
Bằng cách sử dụng cờ --experimental_collect_load_average_in_profiler
được giới thiệu trong Bazel 6.0, Trình phân tích tài nguyên dấu vết JSON sẽ thu thập mức tải hệ thống trung bình trong quá trình gọi.
Hình 1. Hồ sơ bao gồm mức tải hệ thống trung bình.
Mức tải cao trong lệnh gọi Bazel có thể là dấu hiệu cho thấy Bazel lên lịch quá nhiều thao tác cục bộ song song cho máy của bạn. Bạn nên xem xét việc điều chỉnh --local_cpu_resources
và --local_ram_resources
, đặc biệt là trong môi trường vùng chứa (ít nhất là cho đến khi #16512 được hợp nhất).
Giám sát mức sử dụng bộ nhớ Bazel
Có hai nguồn chính để biết mức sử dụng bộ nhớ của Bazel, đó là Bazel info
và BEP.
bazel info used-heap-size-after-gc
: Dung lượng bộ nhớ đã sử dụng tính bằng byte sau lệnh gọi đếnSystem.gc()
.- Bazel bench cũng cung cấp các điểm chuẩn cho chỉ số này.
- Ngoài ra, còn có
peak-heap-size
,max-heap-size
,used-heap-size
vàcommitted-heap-size
(xem tài liệu), nhưng ít liên quan hơn.
MemoryMetrics.peak_post_gc_heap_size
của BEP: Kích thước của vùng nhớ khối xếp JVM đỉnh điểm tính bằng byte sau GC (yêu cầu đặt--memory_profile
để cố gắng buộc GC đầy đủ).
Sự hồi quy trong mức sử dụng bộ nhớ thường là do sự hồi quy trong các chỉ số kích thước yêu cầu bản dựng, thường là do việc thêm các phần phụ thuộc hoặc thay đổi trong quá trình triển khai quy tắc.
Để phân tích mức sử dụng bộ nhớ của Bazel ở cấp độ chi tiết hơn, bạn nên sử dụng trình phân tích bộ nhớ tích hợp sẵn cho các quy tắc.
Phân tích bộ nhớ của worker liên tục
Mặc dù trình thực thi liên tục có thể giúp tăng tốc đáng kể các bản dựng (đặc biệt là đối với ngôn ngữ thông dịch), nhưng mức sử dụng bộ nhớ của chúng có thể gây ra vấn đề. Bazel thu thập các chỉ số về worker, cụ thể là trường WorkerMetrics.WorkerStats.worker_memory_in_kb
cho biết lượng bộ nhớ mà worker sử dụng (theo ký hiệu ghi nhớ).
Trình phân tích dấu vết JSON cũng thu thập mức sử dụng bộ nhớ của worker liên tục trong lệnh gọi bằng cách truyền cờ --experimental_collect_system_network_usage
(mới trong Bazel 6.0).
Hình 2. Hồ sơ bao gồm mức sử dụng bộ nhớ của worker.
Việc giảm giá trị của --worker_max_instances
(mặc định là 4) có thể giúp giảm dung lượng bộ nhớ mà worker ổn định sử dụng. Chúng tôi đang tích cực nỗ lực để làm cho trình quản lý tài nguyên và trình lập lịch biểu của Bazel trở nên thông minh hơn, nhờ đó, trong tương lai, bạn sẽ ít phải điều chỉnh chi tiết như vậy hơn.
Giám sát lưu lượng truy cập mạng cho các bản dựng từ xa
Trong quá trình thực thi từ xa, Bazel sẽ tải các cấu phần phần mềm được tạo ra do thực thi các hành động. Do đó, băng thông mạng có thể ảnh hưởng đến hiệu suất của bản dựng.
Nếu đang sử dụng phương thức thực thi từ xa cho các bản dựng của mình, bạn nên cân nhắc giám sát lưu lượng truy cập mạng trong lệnh gọi bằng cách sử dụng proto NetworkMetrics.SystemNetworkStats
từ BEP (cần truyền --experimental_collect_system_network_usage
).
Hơn nữa, hồ sơ theo dõi JSON cho phép bạn xem mức sử dụng mạng trên toàn hệ thống trong suốt quá trình xây dựng bằng cách truyền cờ --experimental_collect_system_network_usage
(mới trong Bazel 6.0).
Hình 3. Hồ sơ bao gồm mức sử dụng mạng trên toàn hệ thống.
Mức sử dụng mạng cao nhưng khá phẳng khi sử dụng quá trình thực thi từ xa có thể cho thấy rằng mạng là điểm tắc nghẽn trong bản dựng của bạn. Nếu bạn chưa sử dụng mạng này, hãy cân nhắc bật Bản dựng không có Byte bằng cách truyền --remote_download_minimal
.
Điều này sẽ giúp tăng tốc bản dựng bằng cách tránh tải các cấu phần phần mềm trung gian không cần thiết.
Một cách khác là định cấu hình bộ nhớ đệm trên ổ đĩa cục bộ để tiết kiệm băng thông tải xuống.