Файлы порядка — это относительно новая техника оптимизации компоновщика. Эти файлы порядка представляют собой текстовые файлы, содержащие символы, обозначающие функции. Компоновщики, такие как lld, используют файлы порядка для размещения функций в определенном порядке. Такие бинарные файлы или библиотеки с упорядоченными символами уменьшают количество ошибок страничного доступа и улучшают время запуска программы благодаря эффективной загрузке символов во время холодного запуска программы.
Добавить функции работы с файлами заказов в ваше приложение можно, выполнив три шага:
- Generate profiles and mapping file
- Создайте файл заказов на основе файлов профилей и сопоставления.
- Используйте файл порядка размещения символов во время сборки релизной версии.
Generate Order File
Generating an order file require three steps:
- Создайте инструментированную версию приложения, которая будет записывать файл с данными о заказе.
- Run the app to generate the profiles
- Post-process the profiles and mapping file
Create an Instrumented Build
Профили генерируются путем запуска инструментированной сборки приложения. Для инструментированной сборки необходимо добавить -forder-file-instrumentation к флагам компилятора и компоновщика, при этом флаг -mllvm -orderfile-write-mapping=<filename>-mapping.txt должен быть добавлен исключительно к флагам компилятора. Флаг instrumentation включает инструментирование файла порядка для профилирования и загружает необходимую для профилирования библиотеку. С другой стороны, флаг mapping просто выводит файл сопоставления, который показывает хеш 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
Обязательно используйте CMAKE_BUILD_TYPE отличный от Debug , чтобы 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)
Other build systems
Скомпилируйте свой код, используя -forder-file-instrumentation -O1 -mllvm -orderfile-write-mapping=mapping.txt .
Параметр -O1 не обязателен, но -O0 использовать не следует.
При компоновке не следует использовать -mllvm -orderfile-write-mapping=mapping.txt .
Все эти флаги не нужны для сборки Release, поэтому их следует контролировать с помощью переменной сборки. Для простоты вы можете настроить все это в файле CMakeLists.txt, как в нашем примере .
Create an Order File Library
Помимо флагов, необходимо настроить файл профилирования, а инструментированный исполняемый файл должен явно инициировать запись профилирования во время своего выполнения.
- Для установки пути к профилю вызовите
__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()для явной записи в файл профиля.
Профили собираются в памяти, и функция dump записывает их в файл. Необходимо убедиться, что функция 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;
}
Run the Build for Profiles
Запустите инструментированное приложение на физическом или виртуальном устройстве, чтобы сгенерировать профили. Вы можете извлечь файлы профилей с помощью 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 Store, поскольку у них нет доступа ко многим папкам.
Postprocess the Profile and Mapping File
Получив профили, вам нужно найти файл сопоставления и преобразовать каждый профиль в шестнадцатеричный формат. Как правило, файл сопоставления находится в папке сборки приложения. Когда у вас есть и профиль, и файл сопоставления, вы можете использовать наш скрипт для генерации файла заказов, взяв файл профиля и соответствующий файл сопоставления.
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 .
Use Order file to Build Application
После генерации файла порядка следует удалить ранее указанные флаги и функции файла порядка, поскольку они предназначены только для этапов генерации. Вам нужно лишь передать флаги компиляции и компоновщика: -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
)
Other build systems
Скомпилируйте свой код, используя -Wl,--symbol-ordering-file=<filename>.orderfile -Wl,--no-warn-symbol-ordering .
Для получения более подробной информации ознакомьтесь с примером файла заказа .
Order file implementation details
Существует множество способов генерации файлов порядка выполнения и их использования при сборке. NDK использует метод LLVM, поэтому он наиболее полезен для ваших разделяемых библиотек C или C++ по сравнению с самим приложением Java или Kotlin. Clang берет каждое имя функции (символ), создает его хеш MD5 и выводит это соотношение в файл сопоставления. Хеш MD5 функции записывается в файл профилирования (формат Profraw) при первом выполнении функции. При последующих выполнениях функция не записывает свой хеш MD5 в файл профилирования, поскольку система стремится избежать дубликатов. В результате в порядок выполнения записывается только первое выполнение функции. Пройдясь по файлу профилирования и файлу сопоставления, вы можете взять каждый хеш MD5, заменить его соответствующей функцией и получить файл порядка выполнения.
Примеры файла профиля в шестнадцатеричном формате и файла сопоставления можно найти в файлах example.prof и example-mapping.txt соответственно.