Заказать файлы

Файлы порядка — это относительно новая техника оптимизации компоновщика. Эти файлы порядка представляют собой текстовые файлы, содержащие символы, обозначающие функции. Компоновщики, такие как lld, используют файлы порядка для размещения функций в определенном порядке. Такие бинарные файлы или библиотеки с упорядоченными символами уменьшают количество ошибок страничного доступа и улучшают время запуска программы благодаря эффективной загрузке символов во время холодного запуска программы.

Добавить функции работы с файлами заказов в ваше приложение можно, выполнив три шага:

  1. Generate profiles and mapping file
  2. Создайте файл заказов на основе файлов профилей и сопоставления.
  3. Используйте файл порядка размещения символов во время сборки релизной версии.

Generate Order File

Generating an order file require three steps:

  1. Создайте инструментированную версию приложения, которая будет записывать файл с данными о заказе.
  2. Run the app to generate the profiles
  3. 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 соответственно.