Il file degli ordini è una tecnica di ottimizzazione del linker recente. Questi file di ordine sono file di testo contenenti simboli che rappresentano funzioni. I linker come gli annunci di questo tipo utilizzano i file di ordine per definire il layout delle funzioni in un ordine specifico. Questi file binari o librerie con simboli ordinati riducono gli errori di pagina e Migliorare i tempi di lancio di un programma grazie al caricamento efficiente dei simboli durante l'avvio a freddo di un programma.
Le funzionalità dei file degli ordini possono essere aggiunte alla tua applicazione seguendo tre passaggi:
- Genera profili e file di mappatura
- Crea un file di ordine dai profili e dal file di mappatura
- Usa il file dell'ordine durante la build della release per definire il layout dei simboli
Genera file degli ordini
La generazione di un file di ordini richiede tre passaggi:
- Crea una versione instrumentata dell'app che scrive il file dell'ordine
- Esegui l'app per generare i profili
- Completa l'elaborazione dei profili e del file di mappatura
Crea una build con strumentazione
I profili vengono generati eseguendo una build dell'applicazione instrumentata.
Una build con strumenti richiede l'aggiunta di -forder-file-instrumentation
a entrambi i campi
i flag di compilatore e linker
-mllvm -orderfile-write-mapping=<filename>-mapping.txt
essere aggiunti rigorosamente ai flag del compilatore.
Il flag di strumentazione consente la strumentazione dei file degli ordini per la profilazione e
carica la libreria specifica necessaria per la profilazione.
D'altra parte, il flag di mappatura restituisce semplicemente il file di mappatura che mostra
Hash MD5 per ogni funzione all'interno del file binario o della libreria.
Inoltre, assicurati di trasmettere qualsiasi flag di ottimizzazione, tranne -O0
, in quanto
il flag di strumentazione e il flag di mappatura ne richiedono uno.
Se non viene passato alcun flag di ottimizzazione, il file di mappatura non viene generato e
build con strumentazione potrebbe restituire hash errati nel file del profilo.
build-ndk
Assicurati di creare con APP_OPTIM=release
in modo che ndk-build utilizzi un'ottimizzazione
diversa da -O0
. Quando si crea con AGP, il rilascio è automatico
le build.
LOCAL_CFLAGS += \
-forder-file-instrumentation \
-mllvm -orderfile-write-mapping=mapping.txt \
LOCAL_LDFLAGS += -forder-file-instrumentation
Marca
Assicurati di utilizzare un'istruzione CMAKE_BUILD_TYPE
diversa da Debug
in modo che CMake utilizzi un'istanza
modalità di ottimizzazione diversa da -O0
. La creazione con AGP è automatica
per le build di release.
target_compile_options(orderfiledemo PRIVATE
-forder-file-instrumentation
-mllvm -orderfile-write-mapping=mapping.txt
)
target_link_options(orderfiledemo PRIVATE -forder-file-instrumentation)
Altri sistemi di compilazione
Compila il codice utilizzando -forder-file-instrumentation -O1 -mllvm
-orderfile-write-mapping=mapping.txt
.
-O1
in particolare non è obbligatorio, ma non utilizzare -O0
.
Ometti -mllvm -orderfile-write-mapping=mapping.txt
durante il collegamento.
Tutti questi flag non sono necessari per una build di release, quindi devono essere controllati una variabile di build. Per semplicità, puoi impostare tutto nel CMakeLists.txt come nel nostro esempio.
Creare una libreria file di ordine
Oltre ai flag, è necessario configurare il file del profilo e il file binario instrumentato deve attivare esplicitamente la scrittura di un profilo durante il suo dell'esecuzione.
- Chiama
__llvm_profile_set_filename(PROFILE_DIR "/<filename>-%m.profraw")
per durante l'impostazione del percorso del profilo. Sebbene l'argomento passato sia<filename>-%m.profraw
, il file del profilo viene salvato come<filename>-%m.profraw.order
. Assicurati che l'app possa scrivere inPROFILE_DIR
e hai accesso alla directory.- A causa della profilazione di molte librerie condivise,
%m
è utile perché si espande in una firma univoca del modulo per la libreria, generando un profilo separato per ogni libreria. Per altri indicatori di pattern, puoi consultare questo link.
- A causa della profilazione di molte librerie condivise,
- Chiama il numero
__llvm_profile_initialize_file()
per configurare il file del profilo - Chiama
__llvm_orderfile_dump()
per scrivere esplicitamente sul file del profilo
I profili vengono raccolti in memoria e la funzione di dump li scrive nel . Devi assicurarti che la funzione di dump venga chiamata alla fine dell'avvio in modo che il file del profilo abbia tutti i simboli fino alla fine dell'avvio.
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;
}
Esegui la creazione per i profili
Esegui l'app con strumentazione su un dispositivo fisico o virtuale per generare
profili.
Puoi estrarre i file del profilo utilizzando 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 .
Come accennato prima, assicurati che la cartella contenente il file del profilo scritto a cui puoi accedere. Se si tratta di un dispositivo virtuale, conviene evitare gli emulatori con il Play Store perché non hai accesso a molte cartelle.
Elaborazione del file di profilo e mappatura
Quando ottieni i profili, devi trovare il file di mappatura e convertirlo per ciascun profilo in formato esadecimale. In genere, puoi trovare il file di mapping nella cartella di creazione dell'app. Quando li hai entrambi, puoi utilizzare il nostro script prendere un file di profilo e il file di mappatura corretto per generare un file di ordine.
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
Per saperne di più sullo script, puoi consultare questo README.
Usa il file di ordine per creare un'applicazione
Dopo aver generato un file di ordine, devi rimuovere i flag precedenti e
le funzioni dei file di ordine, poiché sono concepite solo per i passaggi di generazione.
Devi solo passare -Wl,--symbol-ordering-file=<filename>.orderfile
al
i flag di compile e linker.
A volte i simboli non sono individuabili o non si muovono; pertanto, i simboli vengono
può passare -Wl,--no-warn-symbol-ordering
per eliminare questi avvisi.
build-ndk
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 \
Marca
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
)
Altri sistemi di compilazione
Compila il codice utilizzando -Wl,--symbol-ordering-file=<filename>.orderfile
-Wl,--no-warn-symbol-ordering
.
Per ulteriori informazioni, consulta l'esempio di file degli ordini.
Dettagli di implementazione del file di ordine
Esistono molti modi per generare file di ordine e utilizzarli per la creazione. NDK utilizza il metodo LLVM, quindi è il più utile per il tuo C o C++ condiviso nell'app Java o Kotlin effettiva. Clang prende il nome di ogni funzione (simbolo) e ne crea un hash MD5. restituisce questa relazione con un file di mappatura. L'hash MD5 di una funzione viene scritto nel file di profilo (formato profraw) quando viene eseguita per la prima volta. Qualsiasi esecuzione successiva della funzione non scrive l'hash MD5 nella del profilo poiché vuole evitare duplicati. Di conseguenza, solo la prima esecuzione della funzione viene registrata nell'ordine. Esaminando il file del profilo e il file di mappatura, puoi prendere ogni hash MD5 e sostituirlo con la funzione corrispondente per ottenere un file di ordine.
Esempi di file di profilo in formato esadecimale e file di mappatura trovato come example.prof e example-mapping.txt.