Das Android-Buildsystem für Android 13 und niedriger unterstützt die Verwendung der profilbasierten Optimierung (PGO) von Clang in nativen Android-Modulen mit Blueprint-Buildregeln. Auf dieser Seite wird Clang PGO beschrieben, wie Sie Profile für PGO kontinuierlich generieren und aktualisieren und wie Sie PGO in das Build-System einbinden (mit Anwendungsfall).
Hinweis: In diesem Dokument wird die Verwendung von PGO auf der Android-Plattform beschrieben. Auf dieser Seite finden Sie Informationen zur Verwendung von PGO in einer Android-App.
Clang PGO
Clang kann eine profilbasierte Optimierung mit zwei Arten von Profilen ausführen:
- Instrumentierungsbasierte Profile werden aus einem instrumentierten Zielprogramm generiert. Diese Profile sind detailliert und verursachen einen hohen Laufzeitoverhead.
- Sampling-basierte Profile werden in der Regel durch Hardwarezähler erstellt. Sie verursachen einen geringen Laufzeitoverhead und können ohne Instrumentierung oder Modifikation des Binärcodes erfasst werden. Sie sind weniger detailliert als instrumentierungsbasierte Profile.
Alle Profile sollten aus einer repräsentativen Arbeitslast generiert werden, die das typische Verhalten der App ausübt. Clang unterstützt sowohl AST-basiert (-fprofile-instr-generate
) als auch LLVM-IR-basiert (-fprofile-generate)
). Android unterstützt für die instrumentierungsbasierte PGO jedoch nur LLVM-IR-basiert.
Für die Profilerhebung sind die folgenden Flags erforderlich:
-fprofile-generate
für IR-basierte Instrumente. Bei dieser Option verwendet das Backend einen gewichteten minimalen Spannbaum, um die Anzahl der Instrumentierungsstellen zu reduzieren und ihre Platzierung auf Kanten mit geringem Gewicht zu optimieren. Verwenden Sie diese Option auch für den Verknüpfungsschritt. Der Clang-Treiber übergibt die Profiling-Laufzeit (libclang_rt.profile-arch-android.a
) automatisch an den Linker. Diese Bibliothek enthält Routinen zum Schreiben der Profile auf die Festplatte beim Beenden des Programms.-gline-tables-only
für die stichprobenbasierte Profilerhebung, um nur minimale Informationen zur Fehlerbehebung zu generieren.
Ein Profil kann für die automatische Optimierung mit -fprofile-use=pathname
oder -fprofile-sample-use=pathname
für instrumentierungsbasierte bzw. stichprobenbasierte Profile verwendet werden.
Hinweis:Wenn Clang die Profildaten nach Änderungen am Code nicht mehr verwenden kann, wird eine -Wprofile-instr-out-of-date
-Warnung generiert.
PGO verwenden
So verwenden Sie PGO:
- Erstellen Sie die Bibliothek/Ausführbare Datei mit Instrumentierung, indem Sie
-fprofile-generate
an den Compiler und Linker übergeben. - Erfassen Sie Profile, indem Sie eine repräsentative Arbeitslast auf der instrumentierten Binärdatei ausführen.
- Bearbeiten Sie die Profile mit dem Dienstprogramm
llvm-profdata
. Weitere Informationen finden Sie unter LLVM-Profildateien verarbeiten. - Verwenden Sie die Profile, um PGO anzuwenden, indem Sie
-fprofile-use=<>.profdata
an den Compiler und den Linker übergeben.
Für PGO auf Android-Geräten sollten Profile offline erfasst und zusammen mit dem Code eingecheckt werden, um reproduzierbare Builds zu ermöglichen. Die Profile können verwendet werden, während der Code weiterentwickelt wird, müssen aber regelmäßig neu generiert werden (oder immer dann, wenn Clang warnt, dass die Profile veraltet sind).
Profile erfassen
Clang kann Profile verwenden, die durch Ausführen von Benchmarks mit einem instrumentierten Build der Bibliothek oder durch Stichprobenerhebung von Hardwarezählern beim Ausführen des Benchmarks erfasst wurden. Derzeit unterstützt Android keine Stichprobenerhebung von Profilen. Sie müssen Profile daher mit einem instrumentierten Build erfassen:
- Identifizieren Sie einen Benchmark und die Bibliotheken, die von diesem Benchmark gemeinsam genutzt werden.
- Fügen Sie dem Benchmark und den Bibliotheken
pgo
-Properties hinzu (Details siehe unten). - Erstellen Sie einen Android-Build mit einer instrumentierten Kopie dieser Bibliotheken mit:
make ANDROID_PGO_INSTRUMENT=benchmark
benchmark
ist ein Platzhalter, der die Sammlung von Bibliotheken angibt, die während des Builds instrumentiert wurden. Die tatsächlichen repräsentativen Eingaben (und möglicherweise eine andere ausführbare Datei, die mit einer Bibliothek verknüpft ist, die einem Benchmarking unterzogen wird) sind nicht spezifisch für PGO und fallen nicht in den Geltungsbereich dieses Dokuments.
- Flashen oder synchronisieren Sie den instrumentierten Build auf einem Gerät.
- Führen Sie den Benchmark aus, um Profile zu erfassen.
- Verwenden Sie das Tool
llvm-profdata
(siehe unten), um die Profile nachzubearbeiten und für das Einchecken in den Quellbaum vorzubereiten.
Profile während des Builds verwenden
Überprüfen Sie die Profile in toolchain/pgo-profiles
in einem Android-Baum. Der Name muss mit dem in der untergeordneten Property profile_file
der Property pgo
für die Bibliothek angegebenen Namen übereinstimmen. Das Build-System übergibt die Profildatei beim Erstellen der Bibliothek automatisch an Clang. Sie können die Umgebungsvariable ANDROID_PGO_DISABLE_PROFILE_USE
auf true
setzen, um PGO vorübergehend zu deaktivieren und den Leistungsvorteil zu messen.
Wenn Sie zusätzliche produktspezifische Profilverzeichnisse angeben möchten, hängen Sie sie an die PGO_ADDITIONAL_PROFILE_DIRECTORIES
-Variable in einer BoardConfig.mk
an. Wenn zusätzliche Pfade angegeben werden, werden die Profile in diesen Pfaden über die in toolchain/pgo-profiles
hinweggeschrieben.
Wenn Sie ein Release-Image mit dem Ziel dist
für make
generieren, schreibt das Build-System die Namen der fehlenden Profildateien in $DIST_DIR/pgo_profile_file_missing.txt
. In dieser Datei können Sie sehen, welche Profildateien versehentlich gelöscht wurden, wodurch PGO stillschweigend deaktiviert wird.
PGO in Android.bp-Dateien aktivieren
Wenn Sie PGO in Android.bp
-Dateien für native Module aktivieren möchten, geben Sie einfach das Attribut pgo
an. Diese Property hat die folgenden Untereigenschaften:
Property | Beschreibung |
---|---|
instrumentation
|
Legen Sie true für PGO mit Instrumentierung fest. Der Standardwert ist false . |
sampling
|
Legen Sie true für PGO mit Stichprobenerhebung fest. Der Standardwert ist false . |
benchmarks
|
Liste mit Strings. Dieses Modul wird für das Profiling verwendet, wenn in der Option ANDROID_PGO_INSTRUMENT build ein Benchmark in der Liste angegeben ist. |
profile_file
|
Profildatei (relativ zu toolchain/pgo-profile ), die mit PGO verwendet werden soll. Im Build wird eine Warnung ausgegeben, dass diese Datei nicht existiert, indem sie $DIST_DIR/pgo_profile_file_missing.txt hinzugefügt wird, es sei denn, die Eigenschaft enable_profile_use ist auf false gesetzt ODER die Buildvariable ANDROID_PGO_NO_PROFILE_USE auf true . |
enable_profile_use
|
Legen Sie false fest, wenn Profile beim Build nicht verwendet werden sollen. Kann während des Bootstrappings verwendet werden, um die Profilerhebung zu aktivieren oder PGO vorübergehend zu deaktivieren. Der Standardwert ist true . |
cflags
|
Liste der zusätzlichen Flags, die bei einem instrumentierten Build verwendet werden sollen. |
Beispiel für ein Modul mit PGO:
cc_library { name: "libexample", srcs: [ "src1.cpp", "src2.cpp", ], static: [ "libstatic1", "libstatic2", ], shared: [ "libshared1", ] pgo: { instrumentation: true, benchmarks: [ "benchmark1", "benchmark2", ], profile_file: "example.profdata", } }
Wenn die Benchmarks benchmark1
und benchmark2
ein repräsentatives Verhalten für die Bibliotheken libstatic1
, libstatic2
oder libshared1
zeigen, kann die Eigenschaft pgo
dieser Bibliotheken auch die Benchmarks enthalten. Das defaults
-Modul in Android.bp
kann eine gemeinsame pgo
-Spezifikation für eine Reihe von Bibliotheken enthalten, um zu vermeiden, dass dieselben Build-Regeln für mehrere Module wiederholt werden.
Wenn Sie verschiedene Profildateien auswählen oder PGO für eine Architektur selektiv deaktivieren möchten, geben Sie die Eigenschaften profile_file
, enable_profile_use
und cflags
pro Architektur an. Beispiel (mit fett formatiertem Architekturziel):
cc_library { name: "libexample", srcs: [ "src1.cpp", "src2.cpp", ], static: [ "libstatic1", "libstatic2", ], shared: [ "libshared1", ], pgo: { instrumentation: true, benchmarks: [ "benchmark1", "benchmark2", ], } target: { android_arm: { pgo: { profile_file: "example_arm.profdata", } }, android_arm64: { pgo: { profile_file: "example_arm64.profdata", } } } }
Wenn Sie Verweise auf die Laufzeitbibliothek für das Profiling während des instrumentierungsbasierten Profilings auflösen möchten, übergeben Sie dem Linker das Build-Flag -fprofile-generate
. Statische Bibliotheken, die mit PGO instrumentiert sind, alle gemeinsam genutzten Bibliotheken und alle Binärdateien, die direkt von der statischen Bibliothek abhängen, müssen ebenfalls für PGO instrumentiert werden. Für solche freigegebenen Bibliotheken oder ausführbaren Dateien müssen jedoch keine PGO-Profile verwendet werden und die enable_profile_use
-Eigenschaft kann auf false
gesetzt werden.
Abgesehen von dieser Einschränkung können Sie PGO auf jede statische Bibliothek, jede freigegebene Bibliothek oder jede ausführbare Datei anwenden.
LLVM-Profildateien verarbeiten
Wenn Sie eine instrumentierte Bibliothek oder ausführbare Datei ausführen, wird eine Profildatei mit dem Namen default_unique_id_0.profraw
in /data/local/tmp
erstellt. Dabei ist unique_id
ein numerischer Hashwert, der für diese Bibliothek eindeutig ist. Wenn diese Datei bereits vorhanden ist, wird das neue Profil beim Schreiben der Profile von der Laufzeit für das Profiling mit dem alten Profil zusammengeführt. Hinweis: /data/local/tmp
ist für App-Entwickler nicht zugänglich. Sie sollten stattdessen eine Adresse wie /storage/emulated/0/Android/data/packagename/files
verwenden.
Wenn Sie den Speicherort der Profildatei ändern möchten, legen Sie die Umgebungsvariable LLVM_PROFILE_FILE
zur Laufzeit fest.
Mit dem Dienstprogramm llvm-profdata
wird dann die .profraw
-Datei konvertiert (und gegebenenfalls mehrere .profraw
-Dateien zusammengeführt) in eine .profdata
-Datei:
llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>
profile.profdata
kann dann in den Quellbaum für die Verwendung während des Builds eingecheckt werden.
Wenn während eines Benchmarks mehrere instrumentierte Binärdateien/Bibliotheken geladen werden, generiert jede Bibliothek eine separate .profraw
-Datei mit einer separaten eindeutigen ID. Normalerweise können alle diese Dateien in eine einzige .profdata
-Datei zusammengeführt und für den PGO-Build verwendet werden. Wenn eine Bibliothek von einem anderen Benchmark genutzt wird, muss sie mithilfe von Profilen aus beiden Benchmarks optimiert werden. In diesem Fall ist die Option show
von llvm-profdata
nützlich:
llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw llvm-profdata show -all-functions default_unique_id.profdata
Wenn Sie unique_ids einzelnen Bibliotheken zuordnen möchten, suchen Sie in der show
-Ausgabe für jede unique_id nach einem Funktionsnamen, der für die Bibliothek eindeutig ist.
Fallstudie: PGO für ART
In der Fallstudie wird ART als nachvollziehbares Beispiel vorgestellt. Es ist jedoch keine genaue Beschreibung der tatsächlichen Bibliotheken, die für ART profiliert wurden, oder ihrer Abhängigkeiten.
Der dex2oat
-Compiler in ART hängt von libart-compiler.so
ab, der wiederum von libart.so
abhängt. Die ART-Laufzeit wird hauptsächlich in libart.so
implementiert. Die Benchmarks für den Compiler und die Laufzeit unterscheiden sich:
Benchmark | Profilierte Bibliotheken |
---|---|
dex2oat
|
dex2oat (ausführbar), libart-compiler.so ,
libart.so |
art_runtime
|
libart.so
|
- Fügen Sie
dex2oat
,libart-compiler.so
die folgendepgo
-Property hinzu:pgo: { instrumentation: true, benchmarks: ["dex2oat",], profile_file: "dex2oat.profdata", }
- Fügen Sie
libart.so
die folgendepgo
-Eigenschaft hinzu:pgo: { instrumentation: true, benchmarks: ["art_runtime", "dex2oat",], profile_file: "libart.profdata", }
- Erstellen Sie instrumentierte Builds für die
dex2oat
- undart_runtime
-Benchmarks mit:make ANDROID_PGO_INSTRUMENT=dex2oat make ANDROID_PGO_INSTRUMENT=art_runtime
- Führen Sie die Benchmarks mit
dex2oat
undart_runtime
aus, um Folgendes zu erhalten:- Drei
.profraw
-Dateien vondex2oat
(dex2oat_exe.profdata
,dex2oat_libart-compiler.profdata
unddexeoat_libart.profdata
), die mit der unter LLVM-Profildateien verarbeiten beschriebenen Methode ermittelt wurden. - Eine einzelne
art_runtime_libart.profdata
.
- Drei
- Erstellen Sie eine gemeinsame profdata-Datei für die ausführbare Datei
dex2oat
undlibart-compiler.so
mit:llvm-profdata merge -output=dex2oat.profdata \ dex2oat_exe.profdata dex2oat_libart-compiler.profdata
- Erstellen Sie das Profil für
libart.so
, indem Sie die Profile aus den beiden Benchmarks zusammenführen:llvm-profdata merge -output=libart.profdata \ dex2oat_libart.profdata art_runtime_libart.profdata
Die Rohzahlen für
libart.so
aus den beiden Profilen können unterschiedlich sein, da sich die Benchmarks in der Anzahl der Testfälle und der Dauer unterscheiden, für die sie ausgeführt werden. In diesem Fall können Sie eine gewichtete Zusammenführung verwenden:llvm-profdata merge -output=libart.profdata \ -weighted-input=2,dex2oat_libart.profdata \ -weighted-input=1,art_runtime_libart.profdata
Mit dem obigen Befehl wird dem Profil von
dex2oat
das doppelte Gewicht zugewiesen. Das tatsächliche Gewicht sollte auf der Grundlage von Fachwissen oder Tests ermittelt werden. - Prüfen Sie die Profildateien
dex2oat.profdata
undlibart.profdata
intoolchain/pgo-profiles
für die Verwendung während des Builds.
Alternativ können Sie einen einzelnen instrumentierten Build mit allen Bibliotheken erstellen, die mithilfe der folgenden Tools instrumentiert wurden:
make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime (or) make ANDROID_PGO_INSTRUMENT=ALL
Mit dem zweiten Befehl werden alle PGO-fähigen Module für das Profiling erstellt.