排序檔案是最新的一項連接器最佳化技術。這些排序檔案是文字檔案,內含代表函式的符號。lld 等連接器會使用排序檔案,以特定順序來配置函式。這些二進位檔或程式庫含有已排序的符號,可在程式冷啟動期間有效載入符號,進而減少網頁錯誤,並縮短程式的啟動時間。
您可以按照下列三個步驟,將排序檔案功能新增到應用程式中:
- 產生設定檔和對應檔案
- 透過設定檔和對應檔案建立排序檔案
- 在發布子版本期間使用排序檔案來配置符號
產生排序檔案
產生排序檔案需要三個步驟:
- 建構可編寫排序檔案的檢測版應用程式
- 執行應用程式,產生設定檔
- 為設定檔和對應檔案進行後置處理
建立檢測版本
藉由執行應用程式的檢測版本,系統會產生設定檔。檢測版本需要將 -forder-file-instrumentation
同時新增至編譯器和連結器標記,-mllvm -orderfile-write-mapping=<filename>-mapping.txt
也需嚴謹地新增至編譯器標記上。檢測標記會啟用排序檔案檢測功能來剖析,並載入剖析所需的特定程式庫。另一方面,對應標記只會輸出對應檔案,其中顯示二進位檔或程式庫中每個函式的 MD5 雜湊。
此外,請務必傳遞除 -O0
以外的所有最佳化標記,因為檢測標記和對應標記都需要這個標記。如果您未傳遞最佳化標記,系統就不會產生對應檔案,而檢測版本可能會將錯誤的雜湊輸出到設定檔中。
ndk-build
請務必使用 APP_OPTIM=release
建構,讓 ndk-build 使用 -O0
以外的最佳化模式。您使用 AGP 建構時,系統會對發布子版本自動執行此操作。
LOCAL_CFLAGS += \
-forder-file-instrumentation \
-mllvm -orderfile-write-mapping=mapping.txt \
LOCAL_LDFLAGS += -forder-file-instrumentation
CMake
請務必使用 Debug
以外的 CMAKE_BUILD_TYPE
,讓 CMake 使用 -O0
以外的最佳化模式。您使用 AGP 建構時,系統會對發布子版本自動執行此操作。
target_compile_options(orderfiledemo PRIVATE
-forder-file-instrumentation
-mllvm -orderfile-write-mapping=mapping.txt
)
target_link_options(orderfiledemo PRIVATE -forder-file-instrumentation)
其他建構系統
使用 -forder-file-instrumentation -O1 -mllvm
-orderfile-write-mapping=mapping.txt
編譯程式碼。
具體而言,-O1
並非必要,但請勿使用 -O0
。
請在連結時省略 -mllvm -orderfile-write-mapping=mapping.txt
。
發布子版本不需要這些標記,因此應由建構變化版本控管。為了方便起見,您可以在 CMakeLists.txt 中完成上述所有設定,如範例所示。
建立排序檔案程式庫
除了標記之外,您還需要調整設定檔,檢測的二進位檔也需在執行期間明確觸發設定檔寫入作業。
- 呼叫
__llvm_profile_set_filename(PROFILE_DIR "/<filename>-%m.profraw")
來調整設定檔路徑。雖然傳遞的引數是<filename>-%m.profraw
,但設定檔會儲存為<filename>-%m.profraw.order
。請確保PROFILE_DIR
可由應用程式寫入,且您有權存取該目錄。- 由於要剖析的共用程式庫很多,
%m
就能派上用場,因為它可以展開成為程式庫的唯一模組簽名,從而為每個程式庫產生獨立的設定檔。如需更多模式指定碼,請點選這個連結。
- 由於要剖析的共用程式庫很多,
- 呼叫
__llvm_profile_initialize_file()
即可調整設定檔 - 呼叫
__llvm_orderfile_dump()
即可明確寫入設定檔
系統會在記憶體中收集設定檔,然後交由轉儲函式將其寫入檔案之中。您需要確保在啟動程序結束時呼叫轉儲函式,讓設定檔納入啟動程序結束前的所有符號。
extern "C" {
extern int __llvm_profile_set_filename(const char*);
extern int __llvm_profile_initialize_file(void);
extern int __llvm_orderfile_dump(void);
}
#define PROFILE_DIR "<location-writable-from-app>"
void workload() {
// ...
// run workload
// ...
// set path and write profiles after workload execution
__llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw");
__llvm_profile_initialize_file();
__llvm_orderfile_dump();
return;
}
執行版本以產生設定檔
請在實體或虛擬裝置上執行檢測應用程式,藉此產生設定檔。您可以使用 adb pull
擷取設定檔。
adb shell "run-as <package-name> sh -c 'cat /data/user/0/<package-name>/cache/default-%m.profraw.order' | cat > /data/local/tmp/default-%m.profraw.order"
adb pull /data/local/tmp/default-%m.profraw.order .
如前所述,請先確認您可以存取包含寫入設定檔的資料夾。如果您採用虛擬裝置,則可能需要避免使用 Play 商店的模擬器,因為該模擬器無法存取許多資料夾。
為設定檔和對應檔案進行後置處理
取得設定檔後,您需要找出對應檔案,並將每個設定檔轉換為十六進制格式。一般而言,您可以在應用程式的建構資料夾中找到對應檔案。當您取得設定檔和對應檔案後,可以使用我們的指令碼擷取設定檔和正確的對應檔案,進而產生排序檔案。
Linux/Mac/ChromeOS
hexdump -C default-%m.profraw.order > default-%m.prof
python3 create_orderfile.py --profile-file default-%m.prof --mapping-file <filename>-mapping.txt
Windows
certutil -f -encodeHex default-%m.profraw.order default-%m.prof
python3 create_orderfile.py --profile-file default-%m.prof --mapping-file <filename>-mapping.txt
如要進一步瞭解指令碼,請查看這個 README 檔案。
使用排序檔案建構應用程式
產生排序檔案後,您應移除先前的標記和排序檔案函式,因為這些內容僅適用於產生步驟階段。您只需將 -Wl,--symbol-ordering-file=<filename>.orderfile
傳遞至編譯和連結器標記即可。有時,您可能會找不到符號,或無法移動符號來發出警告,因此不妨傳遞 -Wl,--no-warn-symbol-ordering
隱抑這些警告。
ndk-build
LOCAL_CFLAGS += \
-Wl,--symbol-ordering-file=<filename>.orderfile \
-Wl,--no-warn-symbol-ordering \
LOCAL_LDFLAGS += \
-Wl,--symbol-ordering-file=<filename>.orderfile \
-Wl,--no-warn-symbol-ordering \
CMake
target_compile_options(orderfiledemo PRIVATE
-Wl,--symbol-ordering-file=<filename>.orderfile
-Wl,--no-warn-symbol-ordering
)
target_link_options(orderfiledemo PRIVATE
-Wl,--symbol-ordering-file=<filename>.orderfile
-Wl,--no-warn-symbol-ordering
)
其他建構系統
使用 -Wl,--symbol-ordering-file=<filename>.orderfile
-Wl,--no-warn-symbol-ordering
編譯程式碼。
詳情請參閱排序檔案範例。
排序檔案實作詳情
您可以透過許多方法產生排序檔案並用於建構。NDK 採用 LLVM 方法,因此最適合用於 C 或 C++ 共用程式庫,而非實際的 Java 或 Kotlin 應用程式。Clang 接受各種函式名稱 (符號),會為其建立 MD5 雜湊,並將這個關係輸出至對應檔案。當函式首次執行時,系統會將函式的 MD5 雜湊寫入設定檔中 (profraw 格式)。但函式的任何後續執行作業,都不會將其 MD5 雜湊寫入至設定檔,因為這樣可避免重複。因此,系統只會依序記錄函式的首次執行作業。透過瀏覽設定檔和對應檔案,您可以擷取各個 MD5 雜湊,將其替換為對應的函式,並取得排序檔案。
十六進制格式設定檔和對應檔案的範例分別為 example.prof 和 example-mapping.txt。