Thực thi động

Báo cáo sự cố Xem nguồn

Thực thi động là một tính năng trong Bazel, trong đó quá trình thực thi cục bộ và từ xa cùng một hành động được bắt đầu song song, sử dụng kết quả từ nhánh đầu tiên đã kết thúc, huỷ nhánh còn lại. Giải pháp này kết hợp khả năng thực thi và/hoặc bộ nhớ đệm dùng chung lớn của một hệ thống xây dựng từ xa với độ trễ thấp của quá trình thực thi cục bộ, mang đến khả năng tốt nhất của cả hai nền tảng cho các bản dựng sạch và tăng dần.

Trang này mô tả cách bật, điều chỉnh và gỡ lỗi thực thi linh động. Nếu bạn đã thiết lập cả quá trình thực thi cục bộ lẫn từ xa, đồng thời đang cố gắng điều chỉnh các chế độ cài đặt Bazel để đạt được hiệu suất tốt hơn, thì trang này là dành cho bạn. Nếu bạn chưa thiết lập tính năng thực thi từ xa, trước tiên, hãy truy cập trang Remote Execution Overview (Tổng quan về quá trình thực thi từ xa) của Bazel.

Bật tính năng thực thi động?

Mô-đun thực thi động là một phần của Bazel, nhưng để sử dụng tính năng thực thi động, bạn phải có khả năng biên dịch cả cục bộ lẫn từ xa từ cùng một chế độ thiết lập Bazel.

Để bật mô-đun thực thi động, hãy chuyển cờ --internal_spawn_scheduler đến Bazel. Thao tác này sẽ thêm một chiến lược thực thi mới có tên là dynamic. Bây giờ, bạn có thể sử dụng chiến lược này làm chiến lược cho các ghi nhớ mà bạn muốn chạy linh hoạt, chẳng hạn như --strategy=Javac=dynamic. Hãy xem phần tiếp theo để biết cách chọn bộ nhớ để bật tính năng thực thi động.

Đối với bất kỳ ghi nhớ nào sử dụng chiến lược động, các chiến lược thực thi từ xa đều được lấy từ cờ --dynamic_remote_strategy và các chiến lược cục bộ từ cờ --dynamic_local_strategy. Thao tác chuyển --dynamic_local_strategy=worker,sandboxed sẽ đặt giá trị mặc định cho nhánh cục bộ của quá trình thực thi động để thử với các trình thực thi hoặc quá trình thực thi hộp cát theo thứ tự đó. Việc truyền --dynamic_local_strategy=Javac=worker sẽ ghi đè giá trị mặc định chỉ dành cho ghi nhớ Javac. Phiên bản từ xa cũng hoạt động theo cách tương tự. Bạn có thể chỉ định cả hai cờ nhiều lần. Nếu không thể thực thi một hành động cục bộ, thì hành động đó sẽ được thực thi từ xa như bình thường và ngược lại.

Nếu hệ thống từ xa có bộ nhớ đệm, thì cờ --dynamic_local_execution_delay sẽ thêm độ trễ (tính bằng mili giây) vào quá trình thực thi cục bộ sau khi hệ thống từ xa chỉ báo lượt truy cập bộ nhớ đệm. Điều này giúp tránh chạy phương thức thực thi cục bộ khi có nhiều lượt truy cập vào bộ nhớ đệm hơn. Giá trị mặc định là 1000 mili giây, nhưng bạn nên điều chỉnh để thời gian này dài hơn một chút so với thời gian truy cập vào bộ nhớ đệm thường nhận. Thời gian thực tế phụ thuộc vào cả hệ thống từ xa và thời gian của một chuyến khứ hồi. Thông thường, tất cả người dùng của một hệ thống từ xa nhất định đều có giá trị như nhau, trừ phi một vài hệ thống trong số đó ở đủ xa để thêm độ trễ trọn vòng. Bạn có thể sử dụng các tính năng lập hồ sơ Bazel để xem thời gian thông thường đối với các lượt truy cập vào bộ nhớ đệm.

Bạn có thể dùng tính năng thực thi động với chiến lược hộp cát cục bộ cũng như trình thực thi liên tục. Trình chạy ổn định sẽ tự động chạy cùng với hộp cát khi được dùng cùng với quá trình thực thi động và không thể sử dụng trình thực thi đa năng. Trên các hệ thống Darwin và Windows, chiến lược hộp cát có thể bị chậm; bạn có thể truyền --reuse_sandbox_directories để giảm mức hao tổn khi tạo hộp cát trên các hệ thống này.

Quá trình thực thi động cũng có thể chạy bằng chiến lược standalone, mặc dù vì chiến lược standalone phải lấy khoá đầu ra khi bắt đầu thực thi, nên chiến lược từ xa này sẽ không thể hoàn tất trước một cách hiệu quả. Cờ --experimental_local_lockfree_output hỗ trợ giải quyết vấn đề này bằng cách cho phép quá trình thực thi cục bộ ghi trực tiếp vào kết quả, nhưng bị quá trình thực thi từ xa huỷ trước nếu quá trình này kết thúc trước.

Nếu một trong các nhánh của quá trình thực thi động kết thúc trước nhưng không thành công, thì toàn bộ thao tác sẽ không thành công. Đây là một lựa chọn có chủ ý để tránh việc người dùng không để ý thấy những điểm khác biệt giữa quá trình thực thi cục bộ và thực thi từ xa.

Để biết thêm thông tin về cách hoạt động của phương pháp thực thi linh động và phương thức khoá của phương thức này, hãy xem các bài đăng trên blog xuất sắc của Julio Merino

Khi nào nên sử dụng tính năng thực thi động?

Quá trình thực thi động yêu cầu một số hình thức hệ thống thực thi từ xa. Hiện tại, bạn không thể sử dụng hệ thống từ xa chỉ dành cho bộ nhớ đệm, vì nếu thiếu bộ nhớ đệm thì thao tác không thành công sẽ bị coi là không thành công.

Không phải loại hành động nào cũng phù hợp để thực thi từ xa. Ứng dụng phù hợp nhất là những ứng dụng vốn đã nhanh hơn cục bộ, chẳng hạn như bằng cách sử dụng trình thực thi liên tục hoặc những trình chạy đủ nhanh để chi phí thực thi từ xa chiếm ưu thế trong thời gian thực thi. Vì mỗi thao tác được thực thi cục bộ sẽ khoá một số tài nguyên CPU và bộ nhớ, nên việc chạy các thao tác không thuộc các loại đó chỉ trì hoãn quá trình thực thi đối với những thao tác có thực thi đó.

Kể từ bản phát hành 5.0.0-pre.20210708.4, phần phân tích hiệu suất chứa dữ liệu về quá trình thực thi worker, bao gồm cả thời gian dành để hoàn tất yêu cầu công việc sau khi thua một cuộc đua thực thi động. Nếu bạn thấy các luồng worker thực thi động tốn nhiều thời gian đáng kể để thu thập tài nguyên hoặc nhiều thời gian trong async-worker-finish, thì có thể bạn sẽ gặp một số thao tác cục bộ chậm trên các luồng worker đó.

Phân tích dữ liệu có hiệu suất thực thi động kém

Trong hồ sơ sử dụng 8 worker Java ở trên, chúng ta thấy nhiều worker Java đã thua trong các cuộc đua và hoàn tất công việc trên các luồng async-worker-finish. Điều này là do một trình ghi nhớ không phải của nhân viên chiếm đủ tài nguyên để trì hoãn trình thực thi.

Phân tích dữ liệu với hiệu suất thực thi động tốt hơn

Khi chỉ Javac được chạy với tính năng thực thi động, thì chỉ khoảng một nửa số trình thực thi đã bắt đầu bị thua cuộc sau khi bắt đầu công việc.

Cờ --experimental_spawn_scheduler được đề xuất trước đây không được dùng nữa. Tính năng này bật tính năng thực thi linh động và đặt dynamic làm chiến lược mặc định cho mọi hoạt động ghi nhớ, vốn thường dẫn đến các loại vấn đề này.

Hiệu suất

Phương pháp thực thi linh động giả định rằng bạn cần chi tiêu thêm một số tài nguyên để cải thiện hiệu suất tổng thể khi có đủ tài nguyên cục bộ và từ xa. Tuy nhiên, việc sử dụng tài nguyên quá mức có thể làm chậm chính Bazel hoặc máy chạy, hoặc gây áp lực không mong muốn lên một hệ thống từ xa. Có một số lựa chọn để thay đổi hành vi thực thi động:

--dynamic_local_execution_delay trì hoãn quá trình khởi động một nhánh cục bộ trong vài mili giây sau khi nhánh từ xa bắt đầu, nhưng chỉ khi có một lượt truy cập vào bộ nhớ đệm từ xa trong bản dựng hiện tại. Điều này giúp các bản dựng hưởng lợi từ việc lưu vào bộ nhớ đệm từ xa mà không làm lãng phí tài nguyên cục bộ khi nhiều khả năng là hầu hết dữ liệu đầu ra đều có thể được tìm thấy trong bộ nhớ đệm. Tuỳ thuộc vào chất lượng bộ nhớ đệm, việc giảm tốc độ này có thể cải thiện tốc độ bản dựng nhưng sẽ phải sử dụng nhiều tài nguyên cục bộ hơn.

--experimental_dynamic_local_load_factor là một tuỳ chọn thử nghiệm để quản lý tài nguyên nâng cao. Quá trình này sẽ nhận một giá trị từ 0 đến 1, 0 để tắt tính năng này. Khi bạn đặt thành giá trị lớn hơn 0, Bazel sẽ điều chỉnh số lượng hành động đã lên lịch cục bộ khi có nhiều hành động đang chờ được lên lịch. Việc đặt giá trị này thành 1 cho phép lên lịch thực hiện nhiều thao tác như có sẵn CPU (theo --local_cpu_resources). Các giá trị thấp hơn sẽ đặt số lượng thao tác được lên lịch biểu thành ít hơn tương ứng vì số lượng thao tác cao hơn có thể chạy. Điều này nghe có vẻ khác thường, nhưng với một hệ thống từ xa tốt, quá trình thực thi cục bộ sẽ không giúp ích nhiều khi có nhiều thao tác đang chạy và CPU cục bộ được dùng để quản lý các thao tác từ xa hiệu quả hơn.

--experimental_dynamic_slow_remote_time ưu tiên khởi động các nhánh cục bộ khi nhánh từ xa đã chạy trong ít nhất khoảng thời gian này. Thông thường, hành động đã lên lịch gần đây nhất sẽ được ưu tiên vì nó có khả năng chiến thắng cao nhất. Tuy nhiên, nếu hệ thống từ xa đôi khi bị treo hoặc mất thêm nhiều thời gian, thì thao tác này có thể giúp bản dựng tiếp tục hoạt động. Tính năng này không được bật theo mặc định vì tính năng này có thể ẩn các vấn đề xảy ra với hệ thống từ xa cần được khắc phục. Hãy nhớ theo dõi hiệu suất của hệ thống từ xa nếu bạn bật tuỳ chọn này.

Bạn có thể sử dụng --experimental_dynamic_ignore_local_signals để cho phép nhánh từ xa kiểm soát khi một "spawn cục bộ" thoát ra do một tín hiệu nhất định. Điều này chủ yếu hữu ích cùng với các giới hạn tài nguyên của trình thực thi (xem --experimental_worker_memory_limit_mb, --experimental_worker_sandbox_hardening--experimental_sandbox_memory_limit_mb)), trong đó các quy trình của trình thực thi có thể bị dừng khi chúng sử dụng quá nhiều tài nguyên.

Hồ sơ theo dõi JSON chứa một số biểu đồ liên quan đến hiệu suất có thể giúp xác định các cách cải thiện hiệu suất đánh đổi hiệu suất và mức sử dụng tài nguyên.

Khắc phục sự cố

Các vấn đề xảy ra với quá trình thực thi linh động có thể khó khắc phục và khó gỡ lỗi, vì chúng chỉ có thể hiển thị theo một số tổ hợp cụ thể giữa quá trình thực thi cục bộ và từ xa. --debug_spawn_scheduler thêm đầu ra bổ sung từ hệ thống thực thi động có thể giúp gỡ lỗi các vấn đề này. Bạn cũng có thể điều chỉnh cờ --dynamic_local_execution_delay và số lượng công việc từ xa so với công việc cục bộ để tái hiện vấn đề dễ dàng hơn.

Nếu bạn đang gặp vấn đề với quá trình thực thi động bằng cách sử dụng chiến lược standalone, hãy thử chạy mà không cần --experimental_local_lockfree_output hoặc chạy các hành động cục bộ trong hộp cát. Thao tác này có thể làm chậm bản dựng một chút (xem ở trên nếu bạn đang dùng máy Mac hoặc Windows), nhưng sẽ loại bỏ một số nguyên nhân có thể gây ra lỗi.