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ủa cùng một hành động được bắt đầu song song, bằng cách sử dụng đầu ra từ nhánh đầu tiên kết thúc, huỷ nhánh còn lại. Công cụ này kết hợp sức mạnh 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ộ, cung cấp những gì tốt nhất cho các bản dựng sạch và tăng dần.

Trang này mô tả cách bật, tinh chỉnh và gỡ lỗi thực thi động. Nếu bạn đã thiết lập cả chế độ thực thi cục bộ lẫn chế độ thực thi từ xa, đồng thời đang tìm cách điều chỉnh các chế độ cài đặt Bazel để đạt 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 chuyển đến phần Tổng quan về thực thi từ xa của Bazel.

Bật chế độ thực thi động?

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

Để bật mô-đun thực thi linh động, hãy truyền cờ --internal_spawn_scheduler cho 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 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 các thuộc tính ghi nhớ để bật tính năng thực thi linh động.

Đối với bất kỳ ghi nhớ nào sử dụng chiến lược động, chiến lược thực thi từ xa sẽ đượ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 truyền --dynamic_local_strategy=worker,sandboxed sẽ đặt giá trị mặc định cho nhánh cục bộ của chế độ thực thi linh động để thử với các trình thực thi hoặc thực thi trong 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 tính năng ghi nhớ Java. 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ờ này nhiều lần. Nếu không thể thực thi cục bộ một thao tác, thao tác đó 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ủa bạn 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 cho biết đã truy cập vào bộ nhớ đệm. Điều này giúp tránh chạy quá trình 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 nên được điều chỉnh để chỉ dài hơn một chút so với số lượt truy cập vào bộ nhớ đệm thường mất. Thời gian thực tế phụ thuộc vào cả hệ thống từ xa và thời gian khứ hồi. Thông thường, giá trị này sẽ giống nhau cho tất cả người dùng của một hệ thống từ xa nhất định, trừ khi một số người dùng trong số đó đủ xa để thêm độ trễ trọn vòng. Bạn có thể sử dụng các tính năng phân tích tài nguyên của Bazel để xem thời lượng của các lượt truy cập vào bộ nhớ đệm thông thường.

Bạn có thể sử 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ư với trình thực thi liên tục. Các trình thực thi liên tục sẽ tự động chạy bằng hộp cát khi được sử dụng cùng với chế độ thực thi động và không thể sử dụng trình thực thi đa kênh. Trên 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 những hệ thống này.

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

Nếu một trong các nhánh của quá trình thực thi linh độ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 bỏ sót 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 tính năng thực thi linh động và 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 tôi 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ố dạng hệ thống thực thi từ xa. Hiện không thể sử dụng hệ thống từ xa chỉ có bộ nhớ đệm, vì nếu thiếu bộ nhớ đệm sẽ bị coi là hành động 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. Những ứng viên xuất sắc nhất là những ứng viên vốn đã nhanh hơn cục bộ, chẳng hạn như thông qua việc sử dụng trình thực thi liên tục hoặc những ứng viên chạy đủ nhanh đến mức chi phí thực thi từ xa chi phối 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 các thao tác chạy không thuộc các danh mục đó chỉ trì hoãn việc thực thi những thao tác đó.

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

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

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

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

Khi chỉ chạy Javac với chế độ thực thi động, chỉ khoảng một nửa số worker đã 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 đó không còn được dùng nữa. Trình này sẽ bật tính năng thực thi linh động và đặt dynamic làm chiến lược mặc định cho tất cả thao tác ghi nhớ, điều này thường dẫn đến các vấn đề như vậy.

Hiệu suất

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

--dynamic_local_execution_delay trì hoãn việc bắt đầu một nhánh cục bộ 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 quá trình tạo 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 sẽ không lãng phí tài nguyên cục bộ khi có nhiều khả năng tìm thấy hầu hết đầu ra trong bộ nhớ đệm. Tuỳ thuộc vào chất lượng của bộ nhớ đệm, việc giảm tốc độ này có thể cải thiện tốc độ xây dựng, nhưng vì 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 quản lý tài nguyên nâng cao thử nghiệm. Nó lấy giá trị từ 0 đến 1, 0 thì tắt tính năng này. Khi đặt thành giá trị lớn hơn 0, Bazel sẽ điều chỉnh số lượng hành động được 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 sẽ cho phép số lượng thao tác được lên lịch tối đa tuỳ theo CPU có sẵn (theo --local_cpu_resources). Giá trị càng thấp sẽ đặt số lượng thao tác được lên lịch thành ít hơn tương ứng vì số thao tác có sẵn để chạy càng cao. Điều này nghe có vẻ khác thường, nhưng với một hệ thống từ xa hoạt động tốt, quá trình thực thi cục bộ không giúp ích nhiều khi nhiều thao tác đang được chạy và CPU cục bộ sẽ chi tiêu hiệu quả hơn cho việc quản lý các thao tác từ xa.

--experimental_dynamic_slow_remote_time sẽ ưu tiên việc bắt đầu các nhánh cục bộ khi nhánh từ xa chạy ít nhất bằng khoảng thời gian này. Thông thường, hành động được lên lịch gần đây nhất sẽ được ưu tiên vì hành động này có nhiều khả năng chiến thắng 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ì bản dựng có thể tiếp tục được di chuyển. Tính năng này không được bật theo mặc định vì có thể ẩn các vấn đề 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 tiếp quản khi một luồng dữ liệu 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 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ách cải thiện 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 động có thể khó gỡ lỗi và khó gỡ lỗi, vì các vấn đề này chỉ có thể biểu hiện trong một số tổ hợp cụ thể giữa quá trình thực thi cục bộ và thực thi từ xa. --debug_spawn_scheduler thêm kết quả đầu ra bổ sung từ hệ thống thực thi động có thể giúp gỡ lỗi các sự cố này. Bạn cũng có thể điều chỉnh cờ --dynamic_local_execution_delay cũng như số lượng công việc từ xa so với công việc cục bộ để giúp tái hiện các vấn đề dễ dàng hơn.

Nếu bạn gặp sự cố về quá trình thực thi động khi sử dụng chiến lược standalone, hãy thử chạy mà không dùng --experimental_local_lockfree_output hoặc chạy hộp cát hành động cục bộ. 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.