Ordina file

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:

  1. Genera profili e file di mappatura
  2. Crea un file di ordine dai profili e dal file di mappatura
  3. 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:

  1. Crea una versione instrumentata dell'app che scrive il file dell'ordine
  2. Esegui l'app per generare i profili
  3. 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 in PROFILE_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.
  • 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.