Hệ thống xây dựng Android dành cho Android 13 trở xuống hỗ trợ sử dụng tính năng tối ưu hóa theo hướng dẫn hồ sơ (PGO) của Clang trên các mô-đun Android gốc có quy tắc xây dựng bản thiết kế. Trang này mô tả Clang PGO, cách liên tục tạo và cập nhật các cấu hình được sử dụng cho PGO cũng như cách tích hợp PGO với hệ thống xây dựng (có trường hợp sử dụng).
Lưu ý: Tài liệu này mô tả việc sử dụng PGO trong nền tảng Android. Để tìm hiểu về cách sử dụng PGO từ ứng dụng Android, hãy truy cập trang này .
Giới thiệu về Clang PGO
Clang có thể thực hiện tối ưu hóa theo hướng dẫn hồ sơ bằng hai loại hồ sơ:
- Cấu hình dựa trên công cụ đo lường được tạo từ một chương trình mục tiêu được đo lường. Các cấu hình này rất chi tiết và áp đặt chi phí thời gian chạy cao.
- Hồ sơ dựa trên lấy mẫu thường được tạo bằng bộ đếm phần cứng lấy mẫu. Chúng áp đặt chi phí thời gian chạy thấp và có thể được thu thập mà không cần bất kỳ công cụ hoặc sửa đổi nào đối với tệp nhị phân. Chúng ít chi tiết hơn hồ sơ dựa trên thiết bị đo đạc.
Tất cả hồ sơ phải được tạo từ khối lượng công việc đại diện để thực hiện hành vi điển hình của ứng dụng. Trong khi Clang hỗ trợ cả dựa trên AST ( -fprofile-instr-generate
) và dựa trên LLVM IR ( -fprofile-generate)
, Android chỉ hỗ trợ dựa trên LLVM IR cho PGO dựa trên thiết bị đo đạc.
Cần có các cờ sau để xây dựng bộ sưu tập hồ sơ:
-
-fprofile-generate
cho thiết bị dựa trên IR. Với tùy chọn này, phần phụ trợ sử dụng cách tiếp cận cây bao trùm tối thiểu có trọng số để giảm số lượng điểm đo lường và tối ưu hóa vị trí của chúng ở các cạnh có trọng số thấp (cũng sử dụng tùy chọn này cho bước liên kết). Trình điều khiển Clang tự động chuyển thời gian chạy định hình (libclang_rt.profile- arch -android.a
) cho trình liên kết. Thư viện này chứa các thủ tục ghi hồ sơ vào đĩa khi thoát khỏi chương trình. -
-gline-tables-only
để thu thập hồ sơ dựa trên lấy mẫu nhằm tạo ra thông tin gỡ lỗi tối thiểu.
Một cấu hình có thể được sử dụng cho PGO bằng cách sử dụng -fprofile-use= pathname
hoặc -fprofile-sample-use= pathname
cho các cấu hình dựa trên thiết bị đo và lấy mẫu tương ứng.
Lưu ý: Khi các thay đổi được thực hiện đối với mã, nếu Clang không thể sử dụng dữ liệu hồ sơ nữa, nó sẽ tạo ra cảnh báo -Wprofile-instr-out-of-date
.
Sử dụng PGO
Sử dụng PGO bao gồm các bước sau:
- Xây dựng thư viện/có thể thực thi bằng thiết bị đo bằng cách chuyển
-fprofile-generate
tới trình biên dịch và trình liên kết. - Thu thập hồ sơ bằng cách chạy khối lượng công việc đại diện trên tệp nhị phân được đo lường.
- Xử lý hậu kỳ các cấu hình bằng tiện ích
llvm-profdata
(để biết chi tiết, xem Xử lý tệp hồ sơ LLVM ). - Sử dụng các cấu hình để áp dụng PGO bằng cách chuyển
-fprofile-use=<>.profdata
đến trình biên dịch và trình liên kết.
Đối với PGO trong Android, hồ sơ phải được thu thập ngoại tuyến và được kiểm tra cùng với mã để đảm bảo các bản dựng có thể tái tạo. Cấu hình có thể được sử dụng khi mã phát triển nhưng phải được tạo lại định kỳ (hoặc bất cứ khi nào Clang cảnh báo rằng cấu hình đã cũ).
Thu thập hồ sơ
Clang có thể sử dụng các cấu hình được thu thập bằng cách chạy điểm chuẩn bằng cách sử dụng bản dựng thư viện được thiết kế sẵn hoặc bằng cách lấy mẫu bộ đếm phần cứng khi điểm chuẩn được chạy. Tại thời điểm này, Android không hỗ trợ sử dụng bộ sưu tập hồ sơ dựa trên mẫu, do đó bạn phải thu thập hồ sơ bằng cách sử dụng bản dựng được đo lường:
- Xác định một điểm chuẩn và tập hợp các thư viện được thực hiện chung theo điểm chuẩn đó.
- Thêm thuộc tính
pgo
vào điểm chuẩn và thư viện (chi tiết bên dưới). - Tạo bản dựng Android bằng bản sao công cụ của các thư viện này bằng cách sử dụng:
make ANDROID_PGO_INSTRUMENT=benchmark
benchmark
là một trình giữ chỗ xác định tập hợp các thư viện được thiết kế trong quá trình xây dựng. Các đầu vào đại diện thực tế (và có thể là một tệp thực thi khác liên kết với thư viện đang được đo điểm chuẩn) không dành riêng cho PGO và nằm ngoài phạm vi của tài liệu này.
- Flash hoặc đồng bộ hóa bản dựng thiết bị trên thiết bị.
- Chạy điểm chuẩn để thu thập hồ sơ.
- Sử dụng công cụ
llvm-profdata
(được thảo luận bên dưới) để xử lý hậu kỳ các cấu hình và chuẩn bị sẵn sàng để kiểm tra chúng vào cây nguồn.
Sử dụng hồ sơ trong quá trình xây dựng
Kiểm tra các cấu hình trong toolchain/pgo-profiles
trong cây Android. Tên phải khớp với tên được chỉ định trong thuộc tính phụ profile_file
của thuộc tính pgo
cho thư viện. Hệ thống xây dựng tự động chuyển tệp hồ sơ cho Clang khi xây dựng thư viện. Biến môi trường ANDROID_PGO_DISABLE_PROFILE_USE
có thể được đặt thành true
để tạm thời vô hiệu hóa PGO và đo lường lợi ích hiệu suất của nó.
Để chỉ định các thư mục hồ sơ bổ sung dành riêng cho sản phẩm, hãy thêm chúng vào biến tạo PGO_ADDITIONAL_PROFILE_DIRECTORIES
trong BoardConfig.mk
. Nếu các đường dẫn bổ sung được chỉ định, các cấu hình trong các đường dẫn này sẽ ghi đè các cấu hình trong toolchain/pgo-profiles
.
Khi tạo hình ảnh phát hành bằng cách sử dụng mục tiêu dist
tới make
, hệ thống xây dựng sẽ ghi tên của các tệp hồ sơ bị thiếu vào $DIST_DIR/pgo_profile_file_missing.txt
. Bạn có thể kiểm tra tệp này để xem tệp hồ sơ nào đã vô tình bị đánh rơi (điều này sẽ vô hiệu hóa PGO một cách âm thầm).
Kích hoạt PGO trong tệp Android.bp
Để bật PGO trong tệp Android.bp
cho mô-đun gốc, chỉ cần chỉ định thuộc tính pgo
. Thuộc tính này có các thuộc tính phụ sau:
Tài sản | Sự miêu tả |
---|---|
instrumentation | Đặt thành true cho PGO sử dụng thiết bị đo. Mặc định là false . |
sampling | Đặt thành true cho PGO bằng cách lấy mẫu. Mặc định là false . |
benchmarks | Danh sách các chuỗi. Mô-đun này được xây dựng để lập hồ sơ nếu bất kỳ điểm chuẩn nào trong danh sách được chỉ định trong tùy chọn xây dựng ANDROID_PGO_INSTRUMENT . |
profile_file | Tệp hồ sơ (liên quan đến toolchain/pgo-profile ) để sử dụng với PGO. Bản dựng cảnh báo rằng tệp này không tồn tại bằng cách thêm tệp này vào $DIST_DIR/pgo_profile_file_missing.txt trừ khi thuộc tính enable_profile_use được đặt thành false HOẶC biến bản dựng ANDROID_PGO_NO_PROFILE_USE được đặt thành true . |
enable_profile_use | Đặt thành false nếu cấu hình không được sử dụng trong quá trình xây dựng. Có thể được sử dụng trong quá trình khởi động để kích hoạt việc thu thập hồ sơ hoặc tạm thời vô hiệu hóa PGO. Mặc định là true . |
cflags | Danh sách các cờ bổ sung để sử dụng trong quá trình xây dựng công cụ. |
Ví dụ về mô-đun với PGO:
cc_library { name: "libexample", srcs: [ "src1.cpp", "src2.cpp", ], static: [ "libstatic1", "libstatic2", ], shared: [ "libshared1", ] pgo: { instrumentation: true, benchmarks: [ "benchmark1", "benchmark2", ], profile_file: "example.profdata", } }
Nếu điểm chuẩn benchmark1
và benchmark2
thực hiện hành vi đại diện cho các thư viện libstatic1
, libstatic2
hoặc libshared1
, thuộc tính pgo
của các thư viện này cũng có thể bao gồm điểm chuẩn. Mô- defaults
trong Android.bp
có thể bao gồm đặc tả pgo
chung cho một tập hợp thư viện để tránh lặp lại các quy tắc xây dựng giống nhau cho một số mô-đun.
Để chọn các tệp hồ sơ khác nhau hoặc vô hiệu hóa có chọn lọc PGO cho một kiến trúc, hãy chỉ định các thuộc tính profile_file
, enable_profile_use
và cflags
cho mỗi kiến trúc. Ví dụ (với mục tiêu kiến trúc được in đậm ):
cc_library { name: "libexample", srcs: [ "src1.cpp", "src2.cpp", ], static: [ "libstatic1", "libstatic2", ], shared: [ "libshared1", ], pgo: { instrumentation: true, benchmarks: [ "benchmark1", "benchmark2", ], } target: { android_arm: { pgo: { profile_file: "example_arm.profdata", } }, android_arm64: { pgo: { profile_file: "example_arm64.profdata", } } } }
Để giải quyết các tham chiếu đến thư viện thời gian chạy lập hồ sơ trong quá trình lập hồ sơ dựa trên công cụ đo lường, hãy chuyển cờ xây dựng -fprofile-generate
cho trình liên kết. Các thư viện tĩnh được trang bị PGO, tất cả các thư viện dùng chung và bất kỳ tệp nhị phân nào phụ thuộc trực tiếp vào thư viện tĩnh cũng phải được trang bị cho PGO. Tuy nhiên, các thư viện dùng chung hoặc tệp thực thi như vậy không cần sử dụng cấu hình PGO và thuộc tính enable_profile_use
của chúng có thể được đặt thành false
. Ngoài hạn chế này, bạn có thể áp dụng PGO cho bất kỳ thư viện tĩnh, thư viện dùng chung hoặc tệp thực thi nào.
Xử lý tệp hồ sơ LLVM
Việc thực thi một thư viện được điều chỉnh hoặc tệp thực thi sẽ tạo ra một tệp hồ sơ có tên default_ unique_id _0.profraw
trong /data/local/tmp
(trong đó unique_id
là hàm băm số duy nhất cho thư viện này). Nếu tệp này đã tồn tại, thời gian chạy lập hồ sơ sẽ hợp nhất hồ sơ mới với hồ sơ cũ trong khi ghi hồ sơ. Lưu ý rằng nhà phát triển ứng dụng không thể truy cập /data/local/tmp
; thay vào đó họ nên sử dụng một nơi nào đó như /storage/emulated/0/Android/data/ packagename /files
. Để thay đổi vị trí của tệp hồ sơ, hãy đặt biến môi trường LLVM_PROFILE_FILE
khi chạy.
Sau đó, tiện ích llvm-profdata
được sử dụng để chuyển đổi tệp .profraw
(và có thể hợp nhất nhiều tệp .profraw
) thành tệp .profdata
:
llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>
profile.profdata
sau đó có thể được kiểm tra trong cây nguồn để sử dụng trong quá trình xây dựng.
Nếu nhiều tệp nhị phân/thư viện công cụ được tải trong quá trình đo điểm chuẩn, thì mỗi thư viện sẽ tạo một tệp .profraw
riêng biệt có một ID duy nhất riêng biệt. Thông thường, tất cả các tệp này có thể được hợp nhất thành một tệp .profdata
duy nhất và được sử dụng để xây dựng PGO. Trong trường hợp thư viện được thực hiện theo điểm chuẩn khác, thư viện đó phải được tối ưu hóa bằng cách sử dụng cấu hình từ cả hai điểm chuẩn. Trong tình huống này, tùy chọn show
của llvm-profdata
rất hữu ích:
llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw llvm-profdata show -all-functions default_unique_id.profdata
Để ánh xạ các Unique_id tới các thư viện riêng lẻ, hãy tìm kiếm đầu ra show
cho mỗi Unique_id để biết tên hàm duy nhất cho thư viện.
Nghiên cứu điển hình: PGO cho ART
Nghiên cứu trường hợp này trình bày ART như một ví dụ dễ hiểu; tuy nhiên, đây không phải là mô tả chính xác về tập hợp thư viện thực tế được lập hồ sơ cho ART hoặc sự phụ thuộc lẫn nhau của chúng.
Trình biên dịch trước dex2oat
trong ART phụ thuộc vào libart-compiler.so
, do đó phụ thuộc vào libart.so
. Thời gian chạy ART được triển khai chủ yếu trong libart.so
. Điểm chuẩn cho trình biên dịch và thời gian chạy sẽ khác nhau:
Điểm chuẩn | Thư viện hồ sơ |
---|---|
dex2oat | dex2oat (có thể thực thi), libart-compiler.so , libart.so |
art_runtime | libart.so |
- Thêm thuộc tính
pgo
sau vàodex2oat
,libart-compiler.so
:pgo: { instrumentation: true, benchmarks: ["dex2oat",], profile_file: "dex2oat.profdata", }
- Thêm thuộc tính
pgo
sau vàolibart.so
:pgo: { instrumentation: true, benchmarks: ["art_runtime", "dex2oat",], profile_file: "libart.profdata", }
- Tạo các bản dựng được đo lường cho điểm chuẩn
dex2oat
vàart_runtime
bằng cách sử dụng:make ANDROID_PGO_INSTRUMENT=dex2oat make ANDROID_PGO_INSTRUMENT=art_runtime
- Chạy các điểm chuẩn thực hiện
dex2oat
vàart_runtime
để có được:- Ba tệp
.profraw
từdex2oat
(dex2oat_exe.profdata
,dex2oat_libart-compiler.profdata
vàdexeoat_libart.profdata
), được xác định bằng phương pháp được mô tả trong Xử lý tệp hồ sơ LLVM . - Một
art_runtime_libart.profdata
duy nhất.
- Ba tệp
- Tạo một tệp profdata chung cho tệp thực thi
dex2oat
vàlibart-compiler.so
bằng cách sử dụng:llvm-profdata merge -output=dex2oat.profdata \ dex2oat_exe.profdata dex2oat_libart-compiler.profdata
- Lấy hồ sơ cho
libart.so
bằng cách hợp nhất các hồ sơ từ hai điểm chuẩn:llvm-profdata merge -output=libart.profdata \ dex2oat_libart.profdata art_runtime_libart.profdata
Số lượng thô cho
libart.so
từ hai cấu hình có thể khác nhau do điểm chuẩn khác nhau về số lượng trường hợp thử nghiệm và thời lượng chúng chạy. Trong trường hợp này, bạn có thể sử dụng hợp nhất có trọng số:llvm-profdata merge -output=libart.profdata \ -weighted-input=2,dex2oat_libart.profdata \ -weighted-input=1,art_runtime_libart.profdata
Lệnh trên gán trọng số gấp đôi cho cấu hình từ
dex2oat
. Trọng lượng thực tế phải được xác định dựa trên kiến thức hoặc thử nghiệm về miền. - Kiểm tra các tệp hồ sơ
dex2oat.profdata
vàlibart.profdata
trongtoolchain/pgo-profiles
để sử dụng trong quá trình xây dựng.
Ngoài ra, hãy tạo một bản dựng được đo lường duy nhất với tất cả các thư viện được đo lường bằng cách sử dụng:
make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime (or) make ANDROID_PGO_INSTRUMENT=ALL
Lệnh thứ hai xây dựng tất cả các mô-đun hỗ trợ PGO để lập hồ sơ.