O sistema de build do Android 13 e versões anteriores oferece suporte ao uso da otimização guiada por perfil (PGO, na sigla em inglês) do Clang em módulos Android nativos que têm regras de build de diagrama. Esta página descreve a PGO do Clang, como gerar e atualizar continuamente os perfis usados para a PGO e como integrar a PGO ao sistema de build (com caso de uso).
Observação: este documento descreve o uso da PGO na plataforma Android. Para saber como usar a PGO em um app Android, acesse esta página.
Sobre a PGO do Clang
O Clang pode realizar a otimização guiada por perfil usando dois tipos de perfil:
- Os perfis baseados em instrumentação são gerados a partir de um programa de destino instrumentado. Esses perfis são detalhados e impõem uma sobrecarga de execução alta.
- Os perfis baseados em amostragem geralmente são produzidos por amostragem de contadores de hardware. Eles impõem uma sobrecarga de execução baixa e podem ser coletados sem nenhuma instrumentação ou modificação no binário. Eles são menos detalhados do que os perfis baseados em instrumentação.
Todos os perfis precisam ser gerados a partir de uma carga de trabalho representativa que
exerça o comportamento típico do app. Embora o Clang ofereça suporte a
AST (-fprofile-instr-generate
) e LLVM IR
(-fprofile-generate)
), o Android oferece suporte apenas a LLVM IR para
PGO baseada em instrumentação.
As flags a seguir são necessárias para criar a coleta de perfis:
-fprofile-generate
para instrumentação baseada em IR. Com essa opção, o back-end usa uma abordagem de árvore mínima ponderada para reduzir o número de pontos de instrumentação e otimizar a posição deles para bordas de baixo peso. Use essa opção também para a etapa de vinculação. O driver Clang transmite automaticamente o ambiente de execução de perfil (libclang_rt.profile-arch-android.a
) ao vinculador. Essa biblioteca contém rotinas para gravar os perfis no disco ao sair do programa.-gline-tables-only
para a coleta de perfis baseada em amostragem para gerar informações mínimas de depuração.
Um perfil pode ser usado para a PGO usando
-fprofile-use=pathname
ou
-fprofile-sample-use=pathname
para perfis baseados em instrumentação
e amostragem, respectivamente.
Observação:à medida que as mudanças são feitas no código, se o Clang não puder
mais usar os dados do perfil, ele gerará um
aviso -Wprofile-instr-out-of-date
.
Usar o PGO
O uso da PGO envolve as seguintes etapas:
- Crie a biblioteca/executável com instrumentação transmitindo
-fprofile-generate
ao compilador e ao vinculador. - Colete perfis executando uma carga de trabalho representativa no binário instrumentado.
- Faça o pós-processamento dos perfis usando o utilitário
llvm-profdata
. Para mais detalhes, consulte Como lidar com arquivos de perfil LLVM. - Use os perfis para aplicar a PGO transmitindo
-fprofile-use=<>.profdata
para o compilador e o vinculador.
Para o PGO no Android, os perfis precisam ser coletados off-line e verificados junto com o código para garantir builds reproduzíveis. Os perfis podem ser usados à medida que o código evolui, mas precisam ser regenerados periodicamente (ou sempre que o Clang avisar que os perfis estão desatualizados).
Coletar perfis
O Clang pode usar perfis coletados executando comparativos de mercado usando um build instrumentado da biblioteca ou amostrando contadores de hardware quando o comparativo de mercado é executado. No momento, o Android não oferece suporte à coleta de perfis baseada em amostragem. Portanto, é necessário coletar perfis usando um build instrumentado:
- Identifique um comparativo de mercado e o conjunto de bibliotecas exercido coletivamente por esse comparativo.
- Adicione propriedades
pgo
ao comparativo de mercado e às bibliotecas (detalhes abaixo). - Produza um build do Android com uma cópia instrumentada dessas bibliotecas
usando:
make ANDROID_PGO_INSTRUMENT=benchmark
benchmark
é um marcador de posição que identifica a
coleção de bibliotecas instrumentadas durante o build. As entradas
de exemplo reais (e possivelmente outro executável vinculado a uma biblioteca
sendo comparada) não são específicas para a PGO e estão fora do escopo deste
documento.
- Faça a atualização ou a sincronização do build instrumentado em um dispositivo.
- Execute o comparativo para coletar perfis.
- Use a ferramenta
llvm-profdata
(discutida abaixo) para processar os perfis e deixá-los prontos para serem verificados na árvore de origem.
Usar perfis durante o build
Verifique os perfis em toolchain/pgo-profiles
em uma árvore
do Android. O nome precisa corresponder ao especificado na
subpropriedade profile_file
da propriedade pgo
da
biblioteca. O sistema de build transmite automaticamente o arquivo de perfil para o Clang
ao criar a biblioteca. A variável de ambiente ANDROID_PGO_DISABLE_PROFILE_USE
pode ser definida como true
para
desativar temporariamente o PGO e medir o benefício de desempenho.
Para especificar outros diretórios de perfil específicos do produto, anexe-os à
variável de make PGO_ADDITIONAL_PROFILE_DIRECTORIES
em um
BoardConfig.mk
. Se outros caminhos forem especificados, os perfis nesses caminhos vão substituir os de toolchain/pgo-profiles
.
Ao gerar uma imagem de lançamento usando o destino dist
para
make
, o sistema de build grava os nomes dos arquivos de perfil ausentes
em $DIST_DIR/pgo_profile_file_missing.txt
. Você pode verificar esse
arquivo para saber quais arquivos de perfil foram descartados acidentalmente (o que desativa silenciosamente
o PGO).
Ativar o PGO em arquivos Android.bp
Para ativar a PGO em arquivos Android.bp
para módulos nativos, basta
especificar a propriedade pgo
. Essa propriedade tem as seguintes
subatributos:
Propriedade | Descrição |
---|---|
instrumentation
|
Definido como true para PGO usando instrumentação. O padrão é
false . |
sampling
|
Defina como true para PGO usando amostragem. O padrão é
false . |
benchmarks
|
Lista de strings. Esse módulo é criado para criar perfis se qualquer comparativo
na lista for especificado na opção de build
ANDROID_PGO_INSTRUMENT . |
profile_file
|
Arquivo de perfil (relativo a toolchain/pgo-profile ) para usar
com a PGO. O build avisa que esse arquivo não existe adicionando-o a $DIST_DIR/pgo_profile_file_missing.txt
a menos que a propriedade enable_profile_use seja definida como
false OU a
variável de build ANDROID_PGO_NO_PROFILE_USE seja definida como
true . |
enable_profile_use
|
Defina como false se os perfis não forem usados durante o
build. Pode ser usado durante o bootstrap para ativar a coleta de perfil ou
desativar temporariamente o PGO. O padrão é true . |
cflags
|
Lista de flags adicionais a serem usadas durante um build instrumentado. |
Exemplo de um módulo com 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", } }
Se os comparativos de mercado benchmark1
e benchmark2
exercerem um comportamento representativo para as bibliotecas libstatic1
,
libstatic2
ou libshared1
, a propriedade pgo
dessas bibliotecas também poderá incluir os comparativos de mercado. O
módulo defaults
em Android.bp
pode incluir uma especificação
pgo
comum para um conjunto de bibliotecas para evitar a repetição das
mesmas regras de build para vários módulos.
Para selecionar diferentes arquivos de perfil ou desativar seletivamente a PGO para uma
arquitetura, especifique as propriedades profile_file
,
enable_profile_use
e cflags
por
arquitetura. Exemplo (com o destino da arquitetura em
negrito):
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", } } } }
Para resolver referências à biblioteca de execução de criação de perfil durante
a criação de perfil baseada em instrumentação, transmita a flag de build
-fprofile-generate
ao vinculador. As bibliotecas estáticas instrumentadas
com PGO, todas as bibliotecas compartilhadas e qualquer binário que dependa diretamente da
biblioteca estática também precisam ser instrumentadas para PGO. No entanto, essas bibliotecas
compartilhadas ou executáveis não precisam usar perfis de PGO, e a propriedade
enable_profile_use
delas pode ser definida como false
.
Fora dessa restrição, é possível aplicar a PGO a qualquer biblioteca estática,
compartilhada ou executável.
Processar arquivos de perfil LLVM
A execução de uma biblioteca ou um executável instrumentado produz um arquivo de perfil
chamado default_unique_id_0.profraw
em
/data/local/tmp
, em que unique_id
é um
hash numérico exclusivo para essa biblioteca. Se esse arquivo já existir,
o ambiente de execução de criação de perfil vai mesclar o novo perfil com o antigo ao gravar
os perfis. /data/local/tmp
não é acessível para desenvolvedores
de apps. Eles precisam usar algo como
/storage/emulated/0/Android/data/packagename/files
.
Para mudar o local do arquivo de perfil, defina a variável de ambiente LLVM_PROFILE_FILE
no momento da execução.
O utilitário llvm-profdata
é usado para converter o arquivo .profraw
(e possivelmente
mesclar vários arquivos .profraw
) em um arquivo
.profdata
:
llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>
O profile.profdata
pode ser verificado na árvore
de origem para uso durante o build.
Se vários binários/bibliotecas instrumentados forem carregados durante um comparativo de mercado,
cada biblioteca vai gerar um arquivo .profraw
separado com um ID exclusivo. Normalmente, todos esses arquivos podem ser mesclados em um único arquivo
.profdata
e usados para o build de PGO. Nos casos em que uma biblioteca
é usada por outro comparativo de mercado, ela precisa ser otimizada usando
perfis de ambos os comparativos. Nessa situação, a opção show
de llvm-profdata
é útil:
llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw llvm-profdata show -all-functions default_unique_id.profdata
Para mapear unique_ids para bibliotecas individuais, pesquise a
saída show
para cada unique_id para um nome de função que
seja exclusivo da biblioteca.
Estudo de caso: PGO para ART
O estudo de caso apresenta o ART como um exemplo relacionado, mas não é uma descrição precisa do conjunto real de bibliotecas com perfil para o ART ou suas interdependências.
O compilador dex2oat
antes do tempo no ART depende de
libart-compiler.so
, que, por sua vez, depende de
libart.so
. O ambiente de execução do ART é implementado principalmente em
libart.so
. Os comparativos de mercado para o compilador e o ambiente de execução serão
diferentes:
Benchmark | Bibliotecas com perfil |
---|---|
dex2oat
|
dex2oat (executável), libart-compiler.so ,
libart.so |
art_runtime
|
libart.so
|
- Adicione a seguinte propriedade
pgo
adex2oat
,libart-compiler.so
:pgo: { instrumentation: true, benchmarks: ["dex2oat",], profile_file: "dex2oat.profdata", }
- Adicione a seguinte propriedade
pgo
alibart.so
:pgo: { instrumentation: true, benchmarks: ["art_runtime", "dex2oat",], profile_file: "libart.profdata", }
- Crie builds instrumentados para os comparativos de mercado
dex2oat
eart_runtime
usando:make ANDROID_PGO_INSTRUMENT=dex2oat make ANDROID_PGO_INSTRUMENT=art_runtime
- Execute as comparações usando
dex2oat
eart_runtime
para receber:- Três arquivos
.profraw
dedex2oat
(dex2oat_exe.profdata
,dex2oat_libart-compiler.profdata
edexeoat_libart.profdata
), identificados usando o método descrito em Como gerenciar arquivos de perfil LLVM. - Um único
art_runtime_libart.profdata
.
- Três arquivos
- Produza um arquivo profdata comum para o executável
dex2oat
elibart-compiler.so
usando:llvm-profdata merge -output=dex2oat.profdata \ dex2oat_exe.profdata dex2oat_libart-compiler.profdata
- Para extrair o perfil de
libart.so
, mescle os perfis das duas comparações:llvm-profdata merge -output=libart.profdata \ dex2oat_libart.profdata art_runtime_libart.profdata
As contagens brutas de
libart.so
dos dois perfis podem ser diferentes porque os comparativos variam no número de casos de teste e na duração de execução. Nesse caso, é possível usar uma mesclagem ponderada:llvm-profdata merge -output=libart.profdata \ -weighted-input=2,dex2oat_libart.profdata \ -weighted-input=1,art_runtime_libart.profdata
O comando acima atribui o dobro do peso ao perfil de
dex2oat
. O peso real precisa ser determinado com base no conhecimento de domínio ou na experimentação. - Verifique os arquivos de perfil
dex2oat.profdata
elibart.profdata
emtoolchain/pgo-profiles
para uso durante o build.
Como alternativa, crie um único build instrumentado com todas as bibliotecas instrumentadas usando:
make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime (or) make ANDROID_PGO_INSTRUMENT=ALL
O segundo comando cria todos os módulos ativados para PGO para criação de perfil.