Profil yönlendirmeli optimizasyon (PGO) iyi bilinen bir derleyici optimizasyon tekniğidir. PGO'da bir programın yürütmesinden alınan çalışma zamanı profilleri, satır içine alma ve kod düzeni hakkında optimum seçimler yapmak için derleyici tarafından kullanılır. Bu sayede performans artar ve kod boyutu küçülür.
PGO, aşağıdaki adımlarla uygulamanıza veya kitaplığınıza dağıtılabilir: 1. Temsili bir iş yükü tanımlayın. 2. Profilleri topla. 3. Sürüm derlemesinde profilleri kullanın.
1. Adım: Temsili İş Yükü Tanımlama
Öncelikle, uygulamanız için temsili bir karşılaştırma veya iş yükü belirleyin. İş yükünden toplanan profiller kodda sıcak ve soğuk bölgeleri tanımladığından bu kritik bir adımdır. Derleyici, profilleri kullanırken agresif optimizasyonlar gerçekleştirir ve sıcak bölgeleri satır içine alır. Derleyici, performanstan ödün vermeden soğuk bölgelerin kod boyutunu azaltmayı da tercih edebilir.
İyi bir iş yükünü tanımlamak, performansı genel olarak takip etmek için de faydalıdır.
2. Adım: Profilleri toplayın
Profil toplama işlemi üç adımdan oluşur: - araçlarla yerel kod oluşturma, - araçlı uygulamayı cihazda çalıştırma ve profiller oluşturma ve - profilleri ana makinede birleştirme/işleme sonrası.
Enstrümanlı Derleme Oluşturma
Profiller, 1. adımdaki iş yükü uygulamanın yapılandırılmış bir derlemesinde çalıştırılarak toplanır. Enstrümanlı bir derleme oluşturmak için derleyici ve bağlayıcı işaretlerine -fprofile-generate
ekleyin. Varsayılan derleme sırasında işaret gerekli olmadığından bu işaret, ayrı bir derleme değişkeni tarafından kontrol edilmelidir.
Profil Oluştur
Ardından, göstergeli uygulamayı cihazda çalıştırın ve profiller oluşturun.
Profiller, izlemeli ikili program çalıştırıldığında bellekte toplanır ve çıkışta bir dosyaya yazılır. Ancak atexit
ile kaydedilen işlevler bir Android uygulamasında çağrılmaz; uygulama sadece sonlandırılır.
Uygulamanın/iş yükünün, profil dosyasına bir yol belirlemek ve daha sonra açık bir şekilde profil yazmayı tetiklemek için fazladan işlem yapması gerekir.
- Profil dosyasının yolunu ayarlamak için
__llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw
numaralı telefonu arayın.%m
, birden fazla paylaşılan kitaplık olduğunda yararlıdır. %m`, ilgili kitaplık için benzersiz bir modül imzasına genişler ve böylece her kitaplık için ayrı bir profil elde edilir. Diğer faydalı kalıp belirleyiciler için buraya bakın. PROFILE_DIR, uygulamadan yazılabilen bir dizindir. Çalışma zamanında bu dizini algılamak için demo bölümüne bakın. - Bir profil yazma işlemini açık bir şekilde tetiklemek için
__llvm_profile_write_file
işlevini çağırın.
extern "C" {
extern int __llvm_profile_set_filename(const char*);
extern int __llvm_profile_write_file(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_write_file();
return;
}
Not: İş yükü bağımsız bir ikili programsa profil dosyasının oluşturulması daha basittir. İkili dosyayı çalıştırmadan önce LLVM_PROFILE_FILE
ortam değişkenini %t/default-%m.profraw
olarak ayarlamanız yeterlidir.
İşlem Sonrası Profilleri
Profil dosyaları .profraw biçimindedir. Bunların öncelikle adb pull
kullanılarak cihazdan alınması gerekir. Getirme işleminden sonra, .profraw
değerinden .profdata
değerine dönüştürmek için NDK'daki llvm-profdata
yardımcı programını kullanın. Bu yardımcı program, daha sonra derleyiciye iletilebilir.
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-profdata \
merge --output=pgo_profile.profdata \
<list-of-profraw-files>
Profil dosyası biçimlerinin sürüm uyuşmazlığını önlemek için aynı NDK sürümünden llvm-profdata
ve clang
öğelerini kullanın.
3. Adım: Uygulama Oluşturmak için Profilleri Kullanma
-fprofile-use=<>.profdata
öğesini derleyiciye ve bağlayıcıya geçirerek uygulamanızın sürüm derlemesi sırasında önceki adımdaki profili kullanın. Profiller, kod gelişirken bile kullanılabilir. Clang derleyicisi, kaynak ve profiller arasındaki küçük uyuşmazlıkları tolere edebilir.
Not: Genel olarak, çoğu kitaplık için profiller farklı mimarilerde ortaktır. Ör. kitaplığın arm64 derlemesinden oluşturulan profiller tüm mimarilerde kullanılabilir. Dikkat edilmesi gereken nokta, kitaplıkta mimariye özel kod yolları varsa (arm-x86 ya da 32 bit veya 64 bit) bu tür her yapılandırma için ayrı profiller kullanılmasıdır.
Her şeyi bir araya getirmek
https://github.com/DanAlbert/ndk-samples/tree/pgo/pgo adresinde, bir uygulamadan PGO kullanımı ile ilgili uçtan uca bir demo gösterilmektedir. Bu belgede kısaca gözden geçirilen ek ayrıntılara yer verilmiştir.
- CMake derleme kuralları, araçlarla yerel kod oluşturan bir CMake değişkeninin nasıl ayarlanacağını gösterir. Derleme değişkeni ayarlanmadığında yerel kod, önceden oluşturulmuş PGO profilleri kullanılarak optimize edilir.
- Gelişmiş bir derlemede pgodemo.cpp, profillerin iş yükü yürütme olduğunu yazar.
- Profillerin yazılabilir konumu, çalışma zamanında
applicationContext.cacheDir.toString()
kullanılarak MainActivity.kt dosyasında elde edilir. adb root
gerektirmeden cihazdan profil almak için buradakiadb
tarifini kullanın.