File Urutan

File urutan adalah teknik pengoptimalan penaut terbaru. File urutan ini adalah file teks yang berisi simbol yang menampilkan fungsi. Penaut seperti lld menggunakan file urutan untuk membuat tata letak fungsi dalam urutan tertentu. Biner atau library dengan simbol yang diurutkan ini mengurangi kesalahan halaman dan mengoptimalkan waktu peluncuran program karena pemuatan simbol yang efisien selama cold start program.

Fitur file urutan dapat ditambahkan ke aplikasi Anda dengan mengikuti tiga langkah berikut:

  1. Membuat profil dan file pemetaan
  2. Membuat file urutan dari profil dan file pemetaan
  3. Menggunakan file urutan selama build Rilis untuk membuat tata letak simbol

Membuat File Urutan

Membuat file urutan memerlukan tiga langkah:

  1. Membangun versi berinstrumen aplikasi yang menulis file urutan
  2. Menjalankan aplikasi untuk membuat profil
  3. Melanjutkan pemrosesan profil dan file pemetaan

Membuat Build Berinstrumen

Profil dibuat dengan menjalankan build berinstrumen aplikasi. Build berinstrumen memerlukan penambahan -forder-file-instrumentation ke tanda compiler dan penaut dengan -mllvm -orderfile-write-mapping=<filename>-mapping.txt yang ditambahkan secara khusus ke tanda compiler. Tanda instrumentasi memungkinkan instrumentasi file urutan untuk pembuatan profil dan memuat library tertentu yang diperlukan untuk pembuatan profil. Di sisi lain, tanda pemetaan hanya menghasilkan file pemetaan yang menunjukkan hash MD5 untuk setiap fungsi dalam biner atau library.

Selain itu, pastikan untuk meneruskan tanda pengoptimalan apa pun kecuali -O0, karena tanda instrumentasi dan tanda pemetaan memerlukannya. Jika tidak ada tanda pengoptimalan yang diteruskan, file pemetaan tidak akan dibuat dan build berinstrumen mungkin menghasilkan hash yang salah ke file profil.

ndk-build

Pastikan untuk membangun aplikasi dengan APP_OPTIM=release agar ndk-build menggunakan mode pengoptimalan selain -O0. Jika membangun aplikasi dengan AGP, perilaku ini akan otomatis diterapkan untuk build rilis.

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

LOCAL_LDFLAGS += -forder-file-instrumentation

CMake

Pastikan untuk menggunakan CMAKE_BUILD_TYPE selain Debug sehingga CMake menggunakan mode pengoptimalan selain -O0. Jika membangun aplikasi dengan AGP, perilaku ini akan otomatis diterapkan untuk build rilis.

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

Sistem build lainnya

Kompilasi kode Anda menggunakan -forder-file-instrumentation -O1 -mllvm -orderfile-write-mapping=mapping.txt.

-O1 secara khusus tidak diperlukan, tetapi jangan gunakan -O0.

Hapus -mllvm -orderfile-write-mapping=mapping.txt saat menautkan.

Semua tanda ini tidak diperlukan untuk build Rilis sehingga harus dikontrol oleh variabel build. Agar lebih mudah, Anda dapat menyiapkannya di CMakeLists.txt seperti pada contoh.

Membuat Library File Urutan

Selain tanda, file profil harus disiapkan dan biner berinstrumen harus secara eksplisit memicu penulisan profil selama eksekusi.

  • Panggil __llvm_profile_set_filename(PROFILE_DIR "/<filename>-%m.profraw") untuk menyiapkan jalur profil. Meskipun argumen yang diteruskan adalah <filename>-%m.profraw, file profil disimpan sebagai <filename>-%m.profraw.order. Pastikan PROFILE_DIR dapat ditulis oleh aplikasi dan Anda memiliki akses ke direktorinya.
    • Karena banyaknya pembuatan profil library bersama, %m berguna karena diperluas ke tanda tangan modul unik untuk library, sehingga membuat profil terpisah per library. Untuk penentu pola lainnya, Anda dapat melihat referensi lewat link ini.
  • Panggil __llvm_profile_initialize_file() untuk menyiapkan file profil
  • Panggil __llvm_orderfile_dump() untuk menulis ke file profil secara eksplisit

Profil dikumpulkan di memori dan fungsi dump akan menulisnya ke file. Anda harus memastikan fungsi dump dipanggil di akhir startup sehingga file profil memiliki semua simbol hingga akhir startup.

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

Menjalankan Build untuk Profil

Jalankan aplikasi berinstrumen pada perangkat fisik atau virtual untuk membuat profil. Anda dapat mengekstrak file profil menggunakan 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 .

Seperti yang disebutkan sebelumnya, pastikan Anda dapat mengakses folder yang berisi file profil tertulis. Jika menggunakan perangkat virtual, sebaiknya hindari emulator dengan Play Store karena tidak memiliki akses ke banyak folder.

Melanjutkan Pemrosesan Profil dan File Pemetaan

Setelah mendapatkan profil, Anda perlu menemukan file pemetaan dan mengonversi setiap profil menjadi format heksadesimal. Biasanya, Anda dapat menemukan file pemetaan dalam folder build aplikasi. Jika memiliki keduanya, Anda dapat menggunakan skrip kami untuk mengambil file profil dan file pemetaan yang benar untuk membuat file urutan.

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

Jika ingin membaca selengkapnya tentang skrip, Anda dapat membaca file README ini.

Menggunakan file Urutan untuk Membangun Aplikasi

Setelah membuat file urutan, Anda harus menghapus tanda sebelumnya dan fungsi file urutan karena keduanya hanya dimaksudkan untuk langkah-langkah pembuatan. Anda hanya perlu meneruskan -Wl,--symbol-ordering-file=<filename>.orderfile ke tanda compiler dan penaut. Terkadang, simbol tidak dapat ditemukan atau tidak dapat dipindahkan dan memberikan peringatan, sehingga Anda dapat meneruskan -Wl,--no-warn-symbol-ordering untuk menyembunyikan peringatan ini.

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
)

Sistem build lainnya

Kompilasi kode Anda menggunakan -Wl,--symbol-ordering-file=<filename>.orderfile -Wl,--no-warn-symbol-ordering.

Untuk informasi selengkapnya, lihat contoh file urutan.

Detail implementasi file urutan

Ada banyak cara untuk membuat file urutan dan menggunakannya untuk membangun aplikasi. NDK menggunakan metode LLVM, yang menjadikannya paling berguna untuk library bersama C atau C++ dibandingkan aplikasi Java atau Kotlin aktual. Clang mengambil setiap nama fungsi (simbol) dan membuat hash MD5-nya serta menghasilkan hubungan ini ke file pemetaan. Hash MD5 fungsi ditulis ke dalam file profil (format profraw) saat fungsi dieksekusi untuk pertama kalinya. Setiap eksekusi fungsi berikutnya tidak akan menulis hash MD5-nya ke file profil karena ingin menghindari duplikat. Akibatnya, hanya eksekusi pertama fungsi yang direkam dalam urutan. Dengan memeriksa file profil dan file pemetaan, Anda dapat mengambil setiap hash MD5 dan menggantinya dengan fungsi yang sesuai, lalu mendapatkan file urutan.

Contoh file profil dalam format heksadesimal dan file pemetaan dapat ditemukan sebagai example.prof dan example-mapping.txt.