Pliki zamówień

Plik zamówienia to nowa metoda optymalizacji kreatora linków. Są to pliki tekstowe zawierające symbole reprezentujące funkcje. Łączniki, takie jak lld, używają plików kolejności do układania funkcji w określonej kolejności. Te pliki binarne i biblioteki z uporządkowanymi symbolami ograniczają liczbę błędów stron i skrócić czas uruchamiania programu dzięki skutecznemu ładowaniu symboli podczas zimnego startu programu.

Funkcje pliku zamówienia można dodać do aplikacji, wykonując 3 czynności kroki:

  1. Wygeneruj profile i plik mapowania
  2. Utwórz plik zamówienia na podstawie profili i pliku mapowania
  3. Do układania symboli użyj pliku zamówienia w kompilacji dotyczącej wersji.

Generuj plik zamówienia

Generowanie pliku zamówienia składa się z trzech kroków:

  1. Utwórz instrumentowaną wersję aplikacji, która zapisuje plik zamówienia
  2. Uruchom aplikację, aby wygenerować profile
  3. Przetwarzanie końcowe profili i pliku mapowania

Utwórz kompilację z instrumentacją

Profile są generowane przez uruchomienie zinstrumentowanej kompilacji aplikacji. Kompilacja z instrumentacją wymaga dodania elementu -forder-file-instrumentation do flagi kompilatora i łączącego -mllvm -orderfile-write-mapping=<filename>-mapping.txt były ściśle dodawane do flag kompilatora. Flaga instrumentacji umożliwia instrumentację pliku zamówienia na potrzeby profilowania oraz wczytuje konkretną bibliotekę potrzebną do profilowania. Z drugiej strony flaga mapowania generuje tylko plik mapowania, który pokazuje Skrót MD5 dla każdej funkcji w pliku binarnym lub bibliotece.

Pamiętaj też, by przekazać wszystkie flagi optymalizacji, ale -O0, ponieważ obie flaga instrumentacji i flagi mapowania wymagają jednego. Jeśli nie zostanie przesłana żadna flaga optymalizacji, plik mapowania nie zostanie wygenerowany, a parametr kompilacja instrumentowana może zwrócić do pliku profilu błędne hasze.

ndk-build

Pamiętaj, aby kompilować za pomocą APP_OPTIM=release, aby funkcja ndk-build korzystała z optymalizacji inny niż -O0. Jeśli używasz AGP, ta funkcja jest dostępna automatycznie do tworzenia kampanii.

LOCAL_CFLAGS += \
    -forder-file-instrumentation \
    -mllvm -orderfile-write-mapping=mapping.txt \

LOCAL_LDFLAGS += -forder-file-instrumentation

CMake

Upewnij się, że używasz pola CMAKE_BUILD_TYPE innego niż Debug, więc CMake używa parametru tryb optymalizacji inny niż -O0. W przypadku tworzenia za pomocą AGP jest to ustawienie automatyczne dla kompilacji wersji.

target_compile_options(orderfiledemo PRIVATE
    -forder-file-instrumentation
    -mllvm -orderfile-write-mapping=mapping.txt
)
target_link_options(orderfiledemo PRIVATE -forder-file-instrumentation)

Inne systemy kompilacji

Skompiluj kod za pomocą polecenia -forder-file-instrumentation -O1 -mllvm -orderfile-write-mapping=mapping.txt.

Parametr -O1 nie jest wymagany, ale nie używaj właściwości -O0.

Pomiń -mllvm -orderfile-write-mapping=mapping.txt podczas łączenia.

Żadne z tych flag nie są potrzebne w przypadku kompilacji wersji, więc powinny być kontrolowane przez i zmiennej kompilacji. Dla uproszczenia możesz to zrobić w pliku CMakeLists.txt, jak w naszym sample.

Tworzenie biblioteki plików zamówienia

Oprócz flag trzeba skonfigurować plik profilu oraz instrumentowany plik binarny musi jawnie aktywować zapis profilu podczas

  • Zadzwoń do firmy __llvm_profile_set_filename(PROFILE_DIR "/<filename>-%m.profraw") i poproś o skonfigurować ścieżkę profilu. Mimo że przekazany argument to <filename>-%m.profraw, plik profilu jest zapisywany jako <filename>-%m.profraw.order Upewnij się, że aplikacja PROFILE_DIR może zapisywać tekst i masz dostęp do katalogu.
    • Ze względu na profilowanie wielu bibliotek udostępnionych usługa %m jest przydatna, rozwija się do unikalnego podpisu modułu dla biblioteki, co skutkuje dla każdej biblioteki. Więcej specyfikacji wzorców znajdziesz na ten link.
  • Zadzwoń pod numer __llvm_profile_initialize_file(), aby skonfigurować plik profilu
  • Wywołaj __llvm_orderfile_dump(), aby bezpośrednio zapisać plik profilu

Profile są zbierane w pamięci, a funkcja zrzutu zapisuje je w . Musisz upewnić się, że funkcja zrzutu jest wywoływana po zakończeniu uruchamiania tak aby plik profilu zawierał wszystkie symbole do końca uruchamiania.

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;
}

Uruchamianie kompilacji dla profili

Uruchom aplikację z instrumentami na urządzeniu fizycznym lub wirtualnym, aby wygenerować profili. Pliki profilu możesz rozpakować za pomocą pliku 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 .

Jak wspomnieliśmy wcześniej, upewnij się, że folder zawierający zapisany plik profilu są dostępne dla Ciebie. Jeśli jest to urządzenie wirtualne, lepiej unikać emulatorów w Sklepie Play. z powodu braku dostępu do wielu folderów.

Przetwarzanie końcowej pliku profilu i pliku mapowania

Po pobraniu profili musisz znaleźć plik mapowania i dokonać konwersji do formatu szesnastkowego każdego profilu. Plik mapowania można zwykle znaleźć w folderze kompilacji aplikacji. Jeśli dysponujesz obydwoma, możesz użyć naszego skryptu, pobierz plik profilu i odpowiedni plik mapowania, aby wygenerować plik zamówienia.

Linux/macOS/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

Jeśli chcesz dowiedzieć się więcej o tym skrypcie, tutaj znajdziesz README.

Tworzenie aplikacji przy użyciu pliku zamówienia

Po wygenerowaniu pliku zamówienia usuń wcześniejsze flagi i , ponieważ są one przeznaczone tylko do kroków generowania. Musisz tylko przekazać -Wl,--symbol-ordering-file=<filename>.orderfile do flagą Google Analytics. Czasami symboli nie można znaleźć lub przesunąć, co powoduje wyświetlanie ostrzeżeń. może przekazać -Wl,--no-warn-symbol-ordering, aby powstrzymać te ostrzeżenia.

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
)

Inne systemy kompilacji

Skompiluj kod za pomocą polecenia -Wl,--symbol-ordering-file=<filename>.orderfile -Wl,--no-warn-symbol-ordering.

Więcej informacji znajdziesz w przykładowym pliku zamówienia.

Szczegóły implementacji pliku zamówienia

Pliki zamówień można generować na wiele sposobów i używać ich do tworzenia. NDK wykorzystuje metodę LLVM, więc jest to najbardziej przydatne w przypadku udostępnianych zasobów w języku C lub C++ nad rzeczywistą aplikacją Java lub Kotlin. Clang pobiera każdą nazwę funkcji (symbol) i tworzy jej skrót MD5, zwraca to powiązanie do pliku mapowania. Skrót MD5 funkcji jest zapisywany w pliku profilu (w formacie profraw), gdy jest wykonywana po raz pierwszy. Żadne kolejne wykonania funkcji nie będą zapisywać jej skrótu MD5 w funkcji profilu, ponieważ chce on uniknąć duplikatów. W rezultacie w zamówieniu rejestrowane jest tylko pierwsze wykonanie funkcji. Przeglądając plik profilu i plik mapowania, możesz przyjąć każdy hasz MD5. i zastąp ją odpowiednią funkcją.

Przykłady pliku profilu w formacie szesnastkowym oraz pliku mapowania znajduje się jako example.prof i example-mapping.txt.