É altamente recomendável automatizar a geração de regras de perfil usando a biblioteca Macrobenchmark do Jetpack para reduzir o esforço manual e aumentar a escalonabilidade geral. No entanto, é possível criar e medir manualmente as regras de perfil no seu app.
Definir regras de perfil manualmente
Para definir as regras de perfil manualmente em um app ou módulo de biblioteca, crie
um arquivo chamado baseline-prof.txt
no diretório src/main
. Essa é a
mesma pasta que contém o arquivo AndroidManifest.xml
.
O arquivo especifica uma regra por linha. Cada regra representa um padrão de métodos ou classes de correspondência que precisa ser otimizado no app ou na biblioteca.
A sintaxe dessas regras é um superconjunto do formato de perfil do ART legível por humanos
(HRF, na sigla em inglês) ao usar adb shell profman --dump-classes-and-methods
. Ela
é semelhante à sintaxe para descritores e assinaturas,
mas permite
usar caracteres curinga para simplificar o processo de criação de regras.
O exemplo abaixo mostram algumas regras de perfil de referência incluídas na biblioteca do Jetpack Compose:
HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Landroidx/compose/runtime/ComposerImpl;
Tente modificar as regras de perfil neste exemplo de projeto do Compiler Explorer. O Compiler Explorer oferece suporte apenas ao formato de perfil do ART legível por humanos (HRF, na sigla em inglês). Portanto, não há suporte para caracteres curinga.
Sintaxe de regras
Essas regras podem ter uma de duas formas destinadas a métodos ou classes:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Uma regra de classe usa este padrão:
[CLASS_DESCRIPTOR]
Consulte a tabela abaixo para uma descrição detalhada:
Sintaxe | Descrição |
---|---|
FLAGS |
Representa um ou mais dos caracteres H , S e P para indicar se esse método será sinalizado como Hot , Startup ou Post Startup em relação ao tipo de inicialização. Um método com a flag H indica que ele é "quente", ou seja, chamado várias vezes durante a vida útil do app. Um método com a flag S indica que ele é chamado na inicialização. Um método com a flag P indica que ele é chamado após a inicialização. Uma classe presente nesse arquivo indica que ela é usada durante a inicialização e precisa ser pré-alocada no heap para evitar o custo do carregamento. O compilador do ART emprega várias estratégias de otimização, como a compilação antecipada desses métodos e otimizações de layout no arquivo gerado antecipadamente. |
CLASS_DESCRIPTOR |
Descritor da classe do método. Por exemplo, androidx.compose.runtime.SlotTable tem um descritor de Landroidx/compose/runtime/SlotTable; . Aqui, L é anexado ao formato Dalvik Executable (DEX). |
METHOD_SIGNATURE |
Assinatura do método, incluindo o nome, os tipos de parâmetro e os tipos de retorno. Por exemplo:// LayoutNode.kt fun isPlaced():Boolean { // ... } em LayoutNode tem a assinatura isPlaced()Z . |
Esses padrões podem ter caracteres curinga para que uma única regra inclua vários métodos ou classes. Para receber assistência guiada ao programar usando a sintaxe de regra no Android Studio, consulte o plug-in de perfis de referência do Android.
Este é um exemplo de regra de caractere curinga:
HSPLandroidx/compose/ui/layout/**->**(**)**
Tipos com suporte nas regras de perfil de referência
As regras de perfil de referência oferecem suporte aos tipos abaixo. Para conferir detalhes sobre esses tipos, consulte o formato Dalvik Executable (DEX).
Caractere | Tipo | Descrição |
---|---|---|
B |
byte | Byte assinado |
C |
char | Ponto de código de caractere Unicode codificado em UTF-16 |
D |
double | Valor de ponto flutuante de precisão dupla |
F |
float | Valor de ponto flutuante de precisão única |
I |
int | Número inteiro |
J |
long | Número inteiro longo |
S |
short | Número inteiro curto assinado |
V |
void | Vazio |
Z |
boolean | Verdadeiro ou falso |
L (nome da classe) |
reference | Uma instância de um nome de classe |
Além disso, as bibliotecas podem definir regras que são empacotadas em artefatos do AAR. Ao criar um APK para incluir esses artefatos, as regras são mescladas (de maneira semelhante à mesclagem de manifestos) e compiladas em um perfil ART binário compacto específico para o APK.
O ART aproveita esse perfil quando o APK é usado em dispositivos para
compilar antecipadamente um subconjunto específico do app durante a instalação no Android 9
(nível 28 da API) ou Android 7 (nível 24 da API) com o
ProfileInstaller
.
Coletar perfis de referência manualmente
Você pode gerar um perfil de referência manualmente sem configurar a biblioteca Macrobenchmark e criar automações de interface para as jornadas ideais do usuário. Embora o uso de Macrobenchmarks seja recomendado, isso nem sempre é possível. Por exemplo, se você estiver usando um sistema de build que não seja o Gradle, não será possível usar o plug-in do perfil de referência para Gradle. Nesses casos, é possível coletar manualmente as regras de perfil de referência. Isso será muito mais fácil se você usar um dispositivo ou emulador com a API 34 ou mais recente. É possível fazer isso com níveis de API mais baixos, mas exige acesso root, e você precisaria usar um emulador com uma imagem AOSP. Para coletar regras diretamente, siga estas etapas:
- Instale uma versão de lançamento do app em um dispositivo de teste. Para ter um perfil preciso, o tipo de build do app precisa ser otimizado para R8 e não pode ser depurável.
- Confira se os perfis já não estão compilados.
API 34 e mais recentes
adb shell cmd package compile -f -m verify $PACKAGE_NAME adb shell pm art clear-app-profiles $PACKAGE_NAME
API 33 e anteriores
adb root adb shell cmd package compile --reset $PACKAGE_NAME
Se o APK tiver uma dependência na biblioteca Profile Installer do Jetpack, a biblioteca vai abrir um perfil na primeira inicialização do APK. Isso pode interferir na geração de perfil. Portanto, desative o processo com este comando:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
- Execute o app e navegue manualmente pelas jornadas ideais do usuário para que você quer coletar um perfil.
- Execute o ART para despejar os perfis. Se o APK tiver uma dependência na biblioteca Profile Installer
do Jetpack, use-a para despejar os perfis:
Se você não estiver usando o Profile Installer, despeje os perfis manualmente em um emulador usando este comando:adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver adb shell am force-stop $PACKAGE_NAME
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME adb shell am force-stop $PACKAGE_NAME
- Aguarde pelo menos cinco segundos para que a geração do perfil seja concluída.
- Converta os perfis binários gerados para texto:
API 34 e mais recentes
adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
API 33 e anteriores
Determine se um perfil de referência ou um perfil atual foi criado. Um perfil de referência fica localizado neste local:
/data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
Um perfil atual fica localizado neste local:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Determine a localização do APK:
adb root adb shell pm path $PACKAGE_NAME
Realize a conversão:
adb root adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt
- Use
adb
para extrair o perfil despejado no dispositivo:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
Isso extrai as regras de perfil geradas e as instala no módulo do app. Na próxima vez que você criar o app, o perfil de referência será incluído. Para conferir, siga as etapas em Problemas de instalação.
Avaliar manualmente as melhorias do app
Recomendamos que você meça as melhorias no app com uma comparação. No entanto, se você quiser medir as melhorias manualmente, comece medindo a inicialização do app não otimizada para referência.
PACKAGE_NAME=com.example.app
# Force Stop App adb shell am force-stop $PACKAGE_NAME # Reset compiled state adb shell cmd package compile --reset $PACKAGE_NAME
# Measure App startup # This corresponds to `Time to initial display` metric. adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Em seguida, transfira o perfil de referência por sideload.
# Unzip the Release APK first. unzip release.apk
# Create a ZIP archive. # The name should match the name of the APK. # Copy `baseline.prof{m}` and rename it `primary.prof{m}`. cp assets/dexopt/baseline.prof primary.prof cp assets/dexopt/baseline.profm primary.profm
# Create an archive. zip -r release.dm primary.prof primary.profm
# Confirm that release.dm only contains the two profile files: unzip -l release.dm # Archive: release.dm # Length Date Time Name # --------- ---------- ----- ---- # 3885 1980-12-31 17:01 primary.prof # 1024 1980-12-31 17:01 primary.profm # --------- ------- # 2 files
# Install APK + Profile together. adb install-multiple release.apk release.dm
Para verificar se o pacote foi otimizado na instalação, execute o comando abaixo:
# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME
A saída precisa declarar que o pacote está compilado:
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Agora, é possível medir a performance de inicialização do app como anteriormente, mas sem redefinir o estado compilado. Não redefina o estado compilado do pacote.
# Force stop app adb shell am force-stop $PACKAGE_NAME
# Measure app startup adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Perfis de referência e profgen
Esta seção descreve o que a ferramenta profgen faz ao criar uma versão binária compacta de um perfil de referência.
O Profgen-cli (link em inglês) ajuda na compilação, introspecção e transpilação de perfis do ART. Assim, eles podem ser instalados em dispositivos com tecnologia Android, independentemente da versão do SDK de destino.
Profgen-cli é uma CLI que compila o HRF de um perfil de referência para o
formato compilado. A CLI também é enviada no
repositório cmdline-tools
como parte do SDK
do Android.
Esses recursos estão disponíveis na ramificação studio-main
:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Criar perfis binários compactos com o Profgen-cli
Os comandos disponíveis no Profgen-cli são bin
, validate
e
dumpProfile
. Para conferir os comandos disponíveis, use profgen --help
:
➜ profgen --help
Usage: profgen options_list
Subcommands:
bin - Generate Binary Profile
validate - Validate Profile
dumpProfile - Dump a binary profile to a HRF
Options:
--help, -h -> Usage info
Use o comando bin
para gerar o perfil binário compacto. Confira
a seguir um exemplo de invocação:
profgen bin ./baseline-prof.txt \
--apk ./release.apk \
--map ./obfuscation-map.txt \
--profile-format v0_1_0_p \
--output ./baseline.prof \
Para conferir as opções disponíveis, use profgen bin options_list
:
Usage: profgen bin options_list
Arguments:
profile -> File path to Human Readable profile { String }
Options:
--apk, -a -> File path to apk (always required) { String }
--output, -o -> File path to generated binary profile (always required)
--map, -m -> File path to name obfuscation map { String }
--output-meta, -om -> File path to generated metadata output { String }
--profile-format, -pf [V0_1_0_P] -> The ART profile format version
{ Value should be one of [
v0_1_5_s, v0_1_0_p, v0_0_9_omr1, v0_0_5_o, v0_0_1_n
]
}
--help, -h -> Usage info
O primeiro argumento representa o caminho para o HRF baseline-prof.txt
.
O Profgen-cli também precisa do caminho para o build de lançamento do APK e de um
mapa de ofuscação, que é usado para ofuscar o APK ao
usar o R8 ou o Proguard. Dessa forma, profgen
pode traduzir símbolos de origem no
HRF para os nomes ofuscados correspondentes ao criar o perfil compilado.
Como os formatos de perfis do ART não são compatíveis com versões anteriores ou posteriores, forneça um
formato para que profgen
empacote os metadados do perfil (profm
) que você
pode usar para transcodificar um formato do perfil do ART para outro quando necessário.
Formatos de perfil e versões de plataforma
As seguintes opções estão disponíveis ao escolher um formato de perfil:
Formato do perfil | Versão da plataforma | Nível da API |
---|---|---|
v0_1_5_s | Android S+ | 31+ |
v0_1_0_p | Android P, Q e R | 28-30 |
v0_0_9_omr1 | Android O MR1 | 27 |
v0_0_5_o | Android O | 26 |
v0_0_1_n | Android N | 24-25 |
Copie os arquivos de saída baseline.prof
e baseline.profm
na
pasta assets
ou dexopt
no APK.
Mapas de ofuscação
Você só vai precisar fornecer o mapa de ofuscação se o HRF usar símbolos de origem. Se
o HRF for gerado a partir de um build de lançamento que já está ofuscado e
não houver necessidade de mapeamento, ignore essa opção e copie as saídas na pasta assets
ou dexopt
.
Instalação tradicional de perfis de referência
Tradicionalmente, os perfis de referência são fornecidos a um dispositivo de duas maneiras.
Usar install-multiple
com DexMetadata
Em dispositivos com a API 28 e versões mais recentes, o cliente do Google Play faz o download do payload do APK e do DexMetadata (DM) para uma versão do APK que está sendo instalada. O DM contém as informações de perfil que são repassadas ao Gerenciador de pacotes no dispositivo.
O APK e o DM são instalados como parte de uma única sessão de instalação usando algo como:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Em dispositivos que executam a API de nível 29 e mais recentes, oJetpack
ProfileInstaller fornece um mecanismo
alternativo para instalar um perfil em pacote em assets
ou dexopt
depois que o APK
for instalado no dispositivo. ProfileInstaller
é invocado pela
ProfileInstallReceiver
ou pelo app diretamente.
A biblioteca ProfileInstaller transcodifica o perfil com base na versão do SDK do
dispositivo de destino e copia o perfil para o diretório cur
no dispositivo (um
diretório de preparo específico do pacote para perfis do ART no dispositivo).
Quando o dispositivo está inativo, o perfil é selecionado por um processo chamado
bg-dexopt
no dispositivo.
Transferir um perfil de referência por sideload
Esta seção descreve como instalar um perfil de referência a partir de um APK.
Transmitir com androidx.profileinstaller
Em dispositivos com a API 24 e mais recentes, você pode transmitir um comando para instalar o perfil:
# Broadcast the install profile command - moves binary profile from assets
# to a location where ART uses it for the next compile.
# When successful, the following command prints "1":
adb shell am broadcast \
-a androidx.profileinstaller.action.INSTALL_PROFILE \
<pkg>/androidx.profileinstaller.ProfileInstallReceiver
# Kill the process
am force-stop <pkg>
# Compile the package based on profile
adb shell cmd package compile -f -m speed-profile <pkg>
O ProfileInstaller não está presente na maioria dos APKs com perfis de referência, que estão em cerca de 77 mil de 450 mil apps no Google Play, embora esteja presente em todos os APKs que usam o Compose. Isso ocorre porque as bibliotecas podem fornecer perfis sem declarar uma dependência no ProfileInstaller. A adição de uma dependência em cada biblioteca com um perfil se aplica a partir do Jetpack.
Usar install-multiple
com profgen ou DexMetaData
Em dispositivos com a API 28 e versões mais recentes, você pode transferir um perfil de referência por sideload sem precisar ter a biblioteca ProfileInstaller no app.
Para isso, use o Profgen-cli:
profgen extractProfile \
--apk app-release.apk \
--output-dex-metadata app-release.dm \
--profile-format V0_1_5_S # Select based on device and the preceding table.
# Install APK and the profile together
adb install-multiple appname-release.apk appname-release.dm
Para oferecer suporte a divisões de APK, execute as etapas de extração anteriores do perfil uma vez por APK. No
momento da instalação, transmita cada APK e o arquivo .dm
associado, garantindo que os nomes do APK e
do .dm
correspondam:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Verificação
Para verificar se o perfil está instalado corretamente, siga as etapas em Medir manualmente as melhorias no app.
Despejar o conteúdo de um perfil binário
Para introspecção do conteúdo de uma versão binária compacta de um
perfil de referência, use a opção dumpProfile
do Profgen-cli:
Usage: profgen dumpProfile options_list
Options:
--profile, -p -> File path to the binary profile (always required)
--apk, -a -> File path to apk (always required) { String }
--map, -m -> File path to name obfuscation map { String }
--strict, -s [true] -> Strict mode
--output, -o -> File path for the HRF (always required) { String }
--help, -h -> Usage info
O dumpProfile
precisa do APK porque a representação binária compacta armazena
apenas os deslocamentos DEX e, portanto, precisa que ele reconstrua nomes de classes e
métodos.
O modo estrito está ativado por padrão e executa uma verificação de compatibilidade do
perfil para os arquivos DEX no APK. Se você estiver tentando depurar perfis
gerados por outra ferramenta, talvez ocorram falhas de compatibilidade que
impedem o despejo para investigação. Nesses casos, é possível
desativar o modo estrito com --strict false
. No entanto, na maioria dos casos,
mantenha o modo restrito ativado.
Um mapa de ofuscação é opcional. Quando fornecido, ele ajuda a remapear símbolos ofuscados em versões legíveis para facilitar o uso.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Práticas recomendadas para a performance do SQLite
- Perfis de referência {:#baseline-profiles}
- Wake locks parciais travados