O sistema de compilação do Android para Android 13 e versões anteriores oferece suporte ao uso da otimização guiada por perfil (PGO) do Clang em módulos Android nativos que possuem regras de compilação de blueprint . Esta página descreve o Clang PGO, como gerar e atualizar continuamente perfis usados para PGO e como integrar o PGO ao sistema de compilação (com caso de uso).
NB: Este documento descreve o uso do PGO na plataforma Android. Para saber mais sobre como usar o PGO em um aplicativo Android, visite esta página .
Sobre Clang PGO
Clang pode realizar otimização guiada por perfil usando dois tipos de perfis:
- 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 alta sobrecarga de tempo de execução.
- Perfis baseados em amostragem são normalmente produzidos por contadores de hardware de amostragem. Eles impõem uma baixa sobrecarga de tempo de execução e podem ser coletados sem qualquer instrumentação ou modificação no binário. Eles são menos detalhados que os perfis baseados em instrumentação.
Todos os perfis devem ser gerados a partir de uma carga de trabalho representativa que exercite o comportamento típico do aplicativo. Embora o Clang ofereça suporte baseado em AST ( -fprofile-instr-generate
) e baseado em LLVM IR ( -fprofile-generate)
, o Android oferece suporte apenas baseado em LLVM IR para PGO baseado em instrumentação.
Os seguintes sinalizadores são necessários para construir a coleção de perfis:
-
-fprofile-generate
para instrumentação baseada em IR. Com esta opção, o back-end usa uma abordagem de árvore geradora mínima ponderada para reduzir o número de pontos de instrumentação e otimizar seu posicionamento em arestas de baixo peso (use esta opção também para a etapa de link). O driver Clang passa automaticamente o tempo de execução de criação de perfil (libclang_rt.profile- arch -android.a
) para o vinculador. Esta biblioteca contém rotinas para gravar os perfis no disco ao sair do programa. -
-gline-tables-only
para coleta de perfis baseada em amostragem para gerar informações mínimas de depuração.
Um perfil pode ser usado para PGO usando -fprofile-use= pathname
ou -fprofile-sample-use= pathname
para perfis baseados em instrumentação e amostragem, respectivamente.
Nota: À medida que são feitas alterações 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 PGO
O uso do PGO envolve as seguintes etapas:
- Crie a biblioteca/executável com instrumentação passando
-fprofile-generate
para o compilador e vinculador. - Colete perfis executando uma carga de trabalho representativa no binário instrumentado.
- Pós-processe os perfis usando o utilitário
llvm-profdata
(para obter detalhes, consulte Manipulando arquivos de perfil LLVM ). - Use os perfis para aplicar o PGO passando
-fprofile-use=<>.profdata
para o compilador e vinculador.
Para PGO no Android, os perfis devem ser coletados off-line e verificados junto com o código para garantir compilações reproduzíveis. Os perfis podem ser usados conforme o código evolui, mas devem ser regenerados periodicamente (ou sempre que o Clang avisar que os perfis estão obsoletos).
Colete perfis
Clang pode usar perfis coletados executando benchmarks usando uma compilação instrumentada da biblioteca ou amostrando contadores de hardware quando o benchmark é executado. No momento, o Android não oferece suporte ao uso de coleta de perfis com base em amostragem. Portanto, você deve coletar perfis usando um build instrumentado:
- Identifique um benchmark e o conjunto de bibliotecas exercidas coletivamente por esse benchmark.
- Adicione propriedades
pgo
ao benchmark e às bibliotecas (detalhes abaixo). - Produza uma versão Android com uma cópia instrumentada dessas bibliotecas usando:
make ANDROID_PGO_INSTRUMENT=benchmark
benchmark
é um espaço reservado que identifica a coleção de bibliotecas instrumentadas durante a construção. As entradas representativas reais (e possivelmente outro executável vinculado a uma biblioteca que está sendo avaliada) não são específicas do PGO e estão além do escopo deste documento.
- Atualize ou sincronize a compilação instrumentada em um dispositivo.
- Execute o benchmark para coletar perfis.
- Use a ferramenta
llvm-profdata
(discutida abaixo) para pós-processar os perfis e prepará-los para serem verificados na árvore de origem.
Use perfis durante a construção
Verifique os perfis em toolchain/pgo-profiles
em uma árvore Android. O nome deve corresponder ao especificado na subpropriedade profile_file
da propriedade pgo
da biblioteca. O sistema de compilação passa automaticamente o arquivo de perfil para o Clang ao construir a biblioteca. A variável de ambiente ANDROID_PGO_DISABLE_PROFILE_USE
pode ser definida como true
para desabilitar temporariamente o PGO e medir seu benefício de desempenho.
Para especificar diretórios de perfil adicionais específicos do produto, anexe-os à variável make PGO_ADDITIONAL_PROFILE_DIRECTORIES
em um BoardConfig.mk
. Se caminhos adicionais forem especificados, os perfis nesses caminhos substituirão aqueles em toolchain/pgo-profiles
.
Ao gerar uma imagem de lançamento usando o dist
target para make
, o sistema de compilação grava os nomes dos arquivos de perfil ausentes em $DIST_DIR/pgo_profile_file_missing.txt
. Você pode verificar este arquivo para ver quais arquivos de perfil foram descartados acidentalmente (o que desativa silenciosamente o PGO).
Habilite PGO em arquivos Android.bp
Para ativar o PGO em arquivos Android.bp
para módulos nativos, basta especificar a propriedade pgo
. Esta propriedade possui as seguintes subpropriedades:
Propriedade | Descrição |
---|---|
instrumentation | Definido como true para PGO usando instrumentação. O padrão é false . |
sampling | Definido como true para PGO usando amostragem. O padrão é false . |
benchmarks | Lista de strings. Este módulo é construído para criação de perfil se qualquer benchmark na lista for especificado na opção de construção ANDROID_PGO_INSTRUMENT . |
profile_file | Arquivo de perfil (relativo a toolchain/pgo-profile ) para usar com PGO. A compilação avisa que este arquivo não existe adicionando-o a $DIST_DIR/pgo_profile_file_missing.txt a menos que a propriedade enable_profile_use esteja definida como false OU a variável de compilação ANDROID_PGO_NO_PROFILE_USE esteja definida como true . |
enable_profile_use | Defina como false se os perfis não devem ser usados durante a construção. Pode ser usado durante a inicialização para ativar a coleta de perfis ou desativar temporariamente o PGO. O padrão é true . |
cflags | Lista de sinalizadores adicionais a serem usados durante um build instrumentado. |
Exemplo de 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 benchmarks benchmark1
e benchmark2
exercerem um comportamento representativo para as bibliotecas libstatic1
, libstatic2
ou libshared1
, a propriedade pgo
dessas bibliotecas também poderá incluir os benchmarks. 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 construção para vários módulos.
Para selecionar diferentes arquivos de perfil ou desabilitar seletivamente o PGO para uma arquitetura, especifique as propriedades profile_file
, enable_profile_use
e cflags
por arquitetura. Exemplo (com arquitetura alvo 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 tempo de execução de criação de perfil durante a criação de perfil baseada em instrumentação, passe o sinalizador de compilação -fprofile-generate
para o vinculador. Bibliotecas estáticas instrumentadas com PGO, todas as bibliotecas compartilhadas e qualquer binário que dependa diretamente da biblioteca estática também devem ser instrumentadas para PGO. No entanto, essas bibliotecas ou executáveis compartilhados não precisam usar perfis PGO e sua propriedade enable_profile_use
pode ser definida como false
. Fora desta restrição, você pode aplicar PGO a qualquer biblioteca estática, biblioteca compartilhada ou executável.
Lidar com arquivos de perfil LLVM
A execução de uma biblioteca instrumentada ou executável produz um arquivo de perfil denominado default_ unique_id _0.profraw
em /data/local/tmp
(onde unique_id
é um hash numérico exclusivo desta biblioteca). Se esse arquivo já existir, o tempo de execução de criação de perfil mesclará o novo perfil com o antigo enquanto grava os perfis. Observe que /data/local/tmp
não está acessível para desenvolvedores de aplicativos; eles deveriam usar algum lugar como /storage/emulated/0/Android/data/ packagename /files
. Para alterar o local do arquivo de perfil, configure a variável de ambiente LLVM_PROFILE_FILE
no tempo de execução.
O utilitário llvm-profdata
é então 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>
profile.profdata
pode então ser verificado na árvore de origem para uso durante a construção.
Se vários binários/bibliotecas instrumentados forem carregados durante um benchmark, cada biblioteca gerará um arquivo .profraw
separado com um ID exclusivo separado. Normalmente, todos esses arquivos podem ser mesclados em um único arquivo .profdata
e usados para construção do PGO. Nos casos em que uma biblioteca é exercida por outro benchmark, essa biblioteca deve ser otimizada utilizando perfis de ambos os benchmarks. Nesta situação, a opção show
do 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_id s para bibliotecas individuais, pesquise na saída show
para cada unique_id um nome de função que seja exclusivo da biblioteca.
Estudo de caso: PGO para ART
O estudo de caso apresenta a ART como um exemplo identificável; no entanto, não é uma descrição precisa do conjunto real de bibliotecas perfiladas para ART ou de suas interdependências.
O compilador antecipado dex2oat
no ART depende de libart-compiler.so
, que por sua vez depende de libart.so
. O tempo de execução do ART é implementado principalmente em libart.so
. Os benchmarks para o compilador e o tempo de execução serão diferentes:
Referência | Bibliotecas perfiladas |
---|---|
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 compilações instrumentadas para os benchmarks
dex2oat
eart_runtime
usando:make ANDROID_PGO_INSTRUMENT=dex2oat make ANDROID_PGO_INSTRUMENT=art_runtime
- Execute os benchmarks exercitando
dex2oat
eart_runtime
para obter:- Três arquivos
.profraw
dedex2oat
(dex2oat_exe.profdata
,dex2oat_libart-compiler.profdata
edexeoat_libart.profdata
), identificados usando o método descrito em Manipulando 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
- Obtenha o perfil para
libart.so
mesclando os perfis dos dois benchmarks:llvm-profdata merge -output=libart.profdata \ dex2oat_libart.profdata art_runtime_libart.profdata
As contagens brutas para
libart.so
dos dois perfis podem ser diferentes porque os benchmarks diferem no número de casos de teste e na duração em que são executados. Nesse caso, você pode 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 deve ser determinado com base no conhecimento do domínio ou na experimentação. - Verifique os arquivos de perfil
dex2oat.profdata
elibart.profdata
emtoolchain/pgo-profiles
para uso durante a construção.
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 habilitados para PGO para criação de perfil.