Uso detalhado do Simpleperf

1. Introdução ao Simpleperf

Simpleperf é uma poderosa ferramenta de linha de comando incluída no NDK que pode nos ajudar a analisar o desempenho da CPU de nosso aplicativo. Simpleperf pode nos ajudar a encontrar pontos de acesso de aplicativos, que geralmente estão relacionados a problemas de desempenho, para que possamos analisar e corrigir a origem dos pontos de acesso.

Se preferir usar a linha de comando, você pode usar o Simpleperf diretamente. Simpleperf é uma ferramenta de criação de perfil de CPU de linha de comando de uso geral incluída no NDK para Mac, Linux e Windows.

Para visualizar a documentação completa, primeiro leia Simpleperf https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/README.md .

Informações oficiais:

2. Princípio básico de funcionamento

As CPUs modernas possuem um componente de hardware chamado Unidade de Monitoramento de Desempenho (PMU). A PMU possui contadores de hardware que contam eventos como quantos ciclos de CPU passaram, quantas instruções foram executadas ou quantas falhas de cache ocorreram.

O kernel do Linux agrupa esses contadores de hardware em eventos de desempenho de hardware. Além disso, o kernel Linux fornece eventos de software independentes de hardware e eventos de tracepoint. O kernel do Linux os expõe ao espaço do usuário por meio da chamada de sistema perf_event_open, que é o mecanismo usado pelo simpleperf.

Simpleperf tem três funções principais: estatística, registro e relatório.

O comando Stat fornece um resumo de quantos eventos ocorreram no processo cujo perfil está sendo criado durante um período de tempo. Veja como funciona:

  1. Dadas as opções do usuário, o simpleperf permite a criação de perfil executando uma chamada de sistema para o kernel Linux.
  2. O kernel do Linux ativa contadores ao despachar para um processo com perfil.
  3. Após a criação do perfil, o simpleperf lê os contadores do kernel e relata um resumo dos contadores.

O comando Gravar registra amostras do processo criado durante um período de tempo. Veja como funciona:

  1. Dadas as opções do usuário, o simpleperf permite a criação de perfil executando uma chamada de sistema para o kernel Linux.
  2. Simpleperf cria um buffer de mapeamento entre o simpleperf e o kernel do Linux.
  3. O kernel do Linux ativa contadores ao despachar para um processo com perfil.
  4. Cada vez que ocorre um determinado número de eventos, o kernel do Linux despeja amostras em um buffer mapeado.
  5. Simpleperf lê amostras do buffer do mapa e stat gera perf.data.

O comando Report lê o arquivo "perf.data" e todas as bibliotecas compartilhadas usadas pelo processo de criação de perfil e gera um relatório mostrando onde o tempo é gasto.

3. Requisitos ambientais

Para usar o Simpleperf, é necessário o seguinte ambiente:

  • O App a ser analisado deverá estar rodando em dispositivos Android 5.0 ou superior.
  • Conexão USB do telefone celular à máquina operacional
  • Os aplicativos devem ser depuráveis. Devido a restrições de segurança, apenas aplicativos com android::debuggable definido como true podem ter perfil criado. (Em um dispositivo com acesso root, todos os aplicativos podem ter perfil criado.) No Android Studio, isso significa que precisamos usar o tipo de compilação de depuração, não o tipo de compilação de lançamento.
  • Para poder executar scripts Python , a máquina host deve ter:
    • Python 2.7 ou superior
    • A versão do NDK não deve ser inferior a r13b

Normalmente, a criação de perfil de desempenho de aplicativos Android envolve três etapas:

  1. Preparar aplicação.
  2. Registre dados de perfil.
  3. Gere relatórios de análise que traçam o perfil dos dados.

Caminho de aquisição do Simpleperf: https://android.googlesource.com/platform/prebuilts/simpleperf/

Na página você pode baixar o pacote compactado diretamente e escolher a versão correspondente do NDK (R13 ~ N21) ou master. Recomenda-se selecionar diretamente a versão correspondente ao NDK. Claro, você também pode extrair o repositório diretamente com git.

clone do git https://android.googlesource.com/platform/prebuilts/simpleperf

Olhando para o diretório simpleperf baixado, podemos ver que seu conjunto de ferramentas inclui cliente e host; o cliente é executado no sistema Android e é responsável por coletar dados de desempenho; o host é executado na máquina de desenvolvimento e é responsável por analisar e visualizar dados (Estes arquivos executáveis ​​​​estão em Android e Win/Linux na pasta bin baixada).

Além da pasta bin, existem muitos arquivos de script .py no nível superior. Esses scripts e arquivos de configuração são principalmente scripts infalíveis escritos pelo oficial, você só precisa configurar o arquivo de configuração e pode executar o script diretamente na máquina de desenvolvimento e gerar o resultado final com um clique.

Os scripts Python são divididos em três partes com base em sua funcionalidade:

  1. Scripts como app_profiler.py para simplificar o registro de dados de criação de perfil.
  2. Scripts usados ​​para gerar relatórios de criação de perfil, como report.py, report_html.py, inferno.
  3. Scripts para analisar dados de criação de perfil, como simpleperf_report_lib.py.

Os scripts principais são: app_profiler.py e report.py.

O arquivo executável simpleperf e o script Python estão incluídos em android-ndk\simpleperf. Suas funções são as seguintes:

  • bin/: Contém arquivos executáveis ​​e bibliotecas compartilhadas, incluindo Android e Windows.
  • bin/android/${arch}/simpleperf: O executável simpleperf estático em execução no dispositivo. Onde ${arch} é a arquitetura da CPU do dispositivo de destino, como arm e arm64.
  • bin/${host}/${arch}/simpleperf: arquivo executável simpleperf para o host, suporta apenas geração de relatórios. Entre eles, ${host} é a plataforma do sistema operacional do host, como Linux, e ${arch} é a arquitetura de CPU do host, como x86_64.
  • bin/${host}/${arch}/libsimpleperf_report.${so/dylib/dll}: Biblioteca de geração de relatórios para o host. Entre eles, ${host} refere-se à plataforma do sistema operacional do host e ${arch} é a arquitetura da CPU do host.
  • app_profiler.py: script Python para registrar dados de criação de perfil.
  • binário_cache_builder.py: script Python para construir um cache binário para criação de perfil de dados.
  • report.py: script Python usado para gerar relatórios de criação de perfil e enviá-los para a saída padrão.
  • report_html.py: script Python usado para gerar relatórios de criação de perfil e gerá-los como arquivos html.
  • inferno.sh (ou inferno.bat na plataforma Windows): Ferramenta de script para gerar gráficos em chamas e exibi-los como arquivos html.
  • inferno/: implementação do inferno. Usado por inferno.sh.
  • pprof_proto_generator.py: script Python que converte o formato dos dados de criação de perfil no formato usado pelo pprof.
  • report_sample.py: script Python que converte o formato dos dados de perfil no formato usado pelo FlameGraph.
  • simpleperf_report_lib.py: Uma biblioteca para analisar dados de criação de perfil.

O conteúdo principal do script é ler o arquivo de configuração e, em seguida, executar o comando adb shell.... Na verdade, é essencialmente o mesmo que a entrada da linha de comando. No entanto, se você executá-lo diretamente, não só precisará verificar o significado de cada item de configuração no arquivo de configuração, mas também podem aparecer muitos bugs inesperados.Não é recomendado usar o script diretamente, pois não será a essência .

4. Comandos suportados

Comando debug-unwind: desenrolamento offline baseado em depuração/teste anão para depuração de simpleperf.

Comando Dump: despeja o conteúdo de perf.data para depurar simpleperf.

Comando de ajuda: imprime informações de ajuda para outros comandos.

Comando kmem: coleta informações de alocação de memória do kernel (será substituído pelo script Python).

Comando list: lista todos os tipos de eventos suportados por dispositivos Android.

Comando de registro em log: configure o processamento de arquivos e armazene dados de análise em perf.data.

Comando report: relata os dados de análise em perf.data.

Comando report-sample: relata cada amostra em perf.data para oferecer suporte à integração de simpleperf no Android Studio.

Comando stat: cria perfis de processos e imprime resumos de contadores.

Cada comando suporta diferentes opções, que podem ser visualizadas através da mensagem de ajuda, como no exemplo a seguir:

#Liste todos os comandos. 
$ simpleperf --help 
# Imprime mensagem de ajuda para o comando de registro. 
$ registro simpleperf --help

5. Processo de operação

Método 1: use adb shell para entrar na operação da página móvel

1. Envie o arquivo simpleperf para o telefone celular

O diretório simpleperf/bin/android contém arquivos binários estáticos rodando em Android com diferentes arquiteturas. Abra a janela de comando no diretório arm e execute o comando:

adb push simpleperf dados/dados/

2. Autorize o simpleperf como um arquivo executável legível e gravável:

adb shell 
cd dados/dados/ 
chmod 777 simpleperf

3. Monitore certos processos ou threads específicos

./registo simpleperf -p 4281 (pid ou tid) --duração 30 (tempo/s)

Recebi uma mensagem de erro dizendo que a partição somente leitura não pôde gravar perf.data:

simpleperf E 04-19 15:09:29 4109 4109 record_file_writer.cpp:47] falhou ao abrir o arquivo de registro 'perf.data': somente leitura f

4. Use o parâmetro -o para definir o caminho para armazenar registros.

simpleperf I cmd_record.cpp:729] Gravado por 29,9851 segundos. Inicie o pós-processamento. 
simpleperf I cmd_record.cpp:809] Amostras registradas: 1457. Amostras perdidas: 0.

5. Use o relatório para relatar os dados de análise em perf.data

registro simpleperf -p 17465 - duração 4 -f 1000 -o /data/local/tmp/perf.data --call-graph fp

relatório simpleperf -i /data/perf.data -n --sort dso
simpleperf W 04-19 15:31:17 4564 4564 dso.cpp:274] /data/local/rvdecApp não contém tabela de símbolos 
simpleperf W 04-19 15:31:17 4564 4564 dso.cpp:335] Endereços de símbolos em /proc/kallsyms são todos zero. `echo 0 >/proc/sys/kernel/kptr_restrict` se possível. 
Cmdline: /data/local/tmp/simpleperf record -p 4281 --duration 30 -o /data/perf.data 
Arch: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 125526 
Contagem de eventos: 43633757353 

Amostra de sobrecarga Objeto compartilhado 
88,93% 106529 /data/local/rvdecApp 
8,05% 10560 /system/lib/libc.so 
3,01% 8437 [kernel.kallsyms]

O parâmetro –sort é usado para especificar quais colunas exibir no resultado. Escrevemos apenas um dso (objeto compartilhado dinâmico) aqui, então o resultado exibe apenas uma coluna de “Objeto Compartilhado”, e de acordo com a classificação dso, o resultado tem apenas três linhas.

Se você não adicionar o parâmetro –sort, estas colunas serão exibidas por padrão: Command, Pid, ​​​​Tid, Shared Object, Symbol, que equivale a:

--sort comm,pid,tid,dso,símbolo
  • O parâmetro -n é utilizado para exibir a coluna Sample, indicando quantas Samples foram atingidas nesta linha, e a adição é opcional.
  • Como você pode ver, 88,93% do tempo é gasto em nosso programa testado, o que é esperado.

6. Olhe dentro do app e veja a proporção das funções:

relatório simpleperf -i /data/perf.data --dsos /data/local/rvdecApp --sort símbolo
  • O resultado é o seguinte:
implementerf W 04-19 15:57:34 5046 5046 dso.cpp:274] /data/local/rvdecApp não contém tabela de símbolos 
simpleperf W 04-19 15:57:34 5046 5046 dso.cpp:335] Endereços de símbolos em /proc/kallsyms são todos zero. `echo 0 >/proc/sys/kernel/kptr_restrict` se possível. 
Cmdline: /data/local/tmp/simpleperf record -p 4281 --duration 30 -o /sdcard/perf.data 
Arch: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 106529 
Contagem de eventos: 38804869540 

Amostra de sobrecarga Símbolo 
5,06% 5373 rvdecApp[+24380] 
4,57% 4890 rvdecApp[+24420] 
1,43% 1588 rvdecApp[+13a44] 
1,01% 1083 rvdecApp[+21f94] 
0,94% 999 rvdecApp[+20188] 
...

O parâmetro –dsos é um dos cinco filtros do simpleperf, o que significa filtrar de acordo com os objetos compartilhados dinâmicos especificados e exibir apenas os resultados no dso especificado pelo parâmetro. Todos os 5 filtros são:

–comms: Filtrar por comando, por exemplo: --comm rvdecApp

–pids: pressione pid para vir aqui

–tids: filtrar por tid (id do tópico)

–dsos: filtrar por biblioteca/nome do arquivo executável

–symbols: Filtre por nome da função, por exemplo: --symbols "RVComFunc::getPUMVPredictor(RefBlockInfo*, unsigned int, int, int, unsigned int)". Observe que se houver espaços na função, ela precisa ser delimitada entre aspas duplas.

Como você pode ver, não há nome de função no resultado. Isso porque nosso rvdecApp é uma versão sem tabela de símbolos. Podemos usar um aplicativo com tabela de símbolos para análise.

O arquivo executável do aplicativo com tabela de símbolos pode ser encontrado no diretório obj. Envie-o para o telefone e substitua o arquivo executável original.

Observe que não há necessidade de executar novamente o rvdecApp e coletar novamente o perf.data, você só precisa usar o rvdecApp com a tabela de símbolos durante a análise.

Use também o comando agora:

./simpleperf report -i /data/perf.data -n --dsos /data/local/rvdecApp --sort símbolo
  • Obtenha os seguintes resultados:
Símbolo de amostra suspensa 
10,45% 5354 RVComFunc::DBFShiftedProcess8x8(unsigned char**, int*, unsigned char*, int, unsigned char*, int, bool, bool, bool, bool, unsigned char) 5,55% 3722 RVComFunc::deblockCUTree 
( TCBDataTree*, caractere não assinado**, int não assinado*, int, int, RefBlockInfo*, int, caractere não assinado**, int*, caractere não assinado) 4,49% 3675 
RVComFunc::reconstructInterPredictors(TCUData*, caractere não assinado**, int não assinado *, TRefPicList*, RefBlockInfo*, unsigned int, unsigned int, unsigned int, unsigned int) 
2,25% 3518 RVComFunc::deriveDBFStrengthFUbyMotionInfo(unsigned char*, unsigned char*, int, int, RefBlockInfo*, int, int, unsigned char, char não assinado, bool, bool) 
2,68% 3320 Decodificador::parseBitStream_FrameNew()
2,79% 2927 NEON_DBF_EdgeFilter4_Vertical 
2,52% 2651 RVComFunc::DBFShiftedProcessFu(unsigned char**, int*, unsigned char*, int, unsigned char*, int, int, bool, bool, bool, bool, unsigned char) 2,36% 2553 ( 
anônimo namespace)::decode_gen_vlc(unsigned long const*, int, (namespace anônimo)::VLC*, int, int) 
...

Pode-se observar que a função DBFShiftedProcess8x8 é a função mais demorada e precisa ser otimizada.

Método 2: Use o ambiente Linux e use o script python para operar

1. Execute app-profiler.py

python app_profiler.py -p com.android.settings

Entrando no diretório simpleperf, podemos usar app-profiler.py para criar o perfil de aplicativos Android. O caminho de saída, etc. pode ser modificado no arquivo de configuração app_profiler.py

14:47:33.547 [INFO] (app_profiler.py:206) preparar a criação de perfil 
14:47:33.730 [INFO] (app_profiler.py:208) iniciar a criação de perfil 
14:47:33.806 [INFO] (app_profiler.py:244) executar adb cmd: ['adb', 'shell', '/data/local/tmp/simpleperf', 'record', '-o', '/data/local/tmp/perf.data', '-e tarefa- clock:u -f 1000 -g --duration 10', '--log', 'info', '--app', 'com.afmobi.boomplayer'] 
simpleperf I cmd_record.cpp:696] Gravado por 9,96625 segundos . Inicie o pós-processamento. 
simpleperf W dso.cpp:446] /vendor/lib64/egl/libGLES_mali.so não contém tabela de símbolos 
simpleperf W dso.cpp:446] /vendor/lib64/hw/[email protected] -mediatek.so não contém tabela de símbolos
simpleperf W dso.cpp:446] /data/app/~~EKnZoTKaDLH3FYfxteqUvg==/com.google.android.tricromelibrary_541411734-ozjH9V7NI4SknoCd0t2CPg==/base.apk!/lib/arm64-v8a/libmonochrome_64.so não contém símbolo tabela 
simpleperf W dso.cpp:446] /data/app/~~3WfX5_4-OAPL17xSEBkRfg==/com.afmobi.boomplayer-yFLZq2TqjDUJV1OB-um-UQ==/lib/arm64/libmmkv.so não contém tabela de símbolos 
simpleperf I cmd_record.cpp:771] Amostras registradas: 8647. Amostras perdidas: 0. 
14:47:45.689 [INFO] (app_profiler.py:211) coleta de dados de perfil 
14:47:46.745 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\apex\com.android.runtime\lib64\bionic\libc.so 
14:47:46,770 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\vendor\lib64\ libged.so
14:47:46.800 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\vendor\lib64\egl\libGLES_mali.so 14:47:46.835 [INFO] (binary_cache_builder.py:184) 
use o arquivo atual em binary_cache: binary_cache\system\lib64\libEGL.so 
14:47:46,867 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\system\lib64\libhwui.so 
14:47:46,888 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\system\lib64\libutils.so 
14:47:46,913 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\system\lib64\libgui .so 
14:47:46.932 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\system\lib64\libnativewindow.so 
46.992 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache : binary_cache\system\framework\arm64\boot-framework.oat 
14:47:47,069 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\apex\com.android.art\lib64\libart.so 
14:47:47,130 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\system\framework\arm64\boot.oat 14:47:47,159 [INFO] (binary_cache_builder.py:184) 
use o arquivo atual em binario_cache: binario_cache\system\lib64\libandroid_runtime.so 
14:47:47,179 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binario_cache: binario_cache\system\bin\app_process64
14:47:47,206 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\apex\com.android.vndk.v31\lib64\libhidlbase.so  
14:47:47,230 [INFO] (binary_cache_builder .py:184) use o arquivo atual em binary_cache: binary_cache\system\lib64\libhidlbase.so
14:47:47,260 [INFO] (binary_cache_builder.py :184) use o arquivo atual em binary_cache: binary_cache\system\lib64\[email protected] 
14:47:47,301 [INFO] (binary_cache_builder.py:184) use o arquivo atual em binary_cache: binary_cache\system \lib64\libui.so

2. Execute o script report_html.py para analisar o relatório e produzi-lo

python report_html.py

simpleperf W dso.cpp:448] falhou ao ler símbolos de /data/app/~~3WfX5_4-OAPL17xSEBkRfg==/com.afmobi.boomplayer-yFLZq2TqjDUJV1OB-um-UQ==/lib/arm64/libmmkv.so: Arquivo não encontrado 
Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.afmobi.boomplayer Arch 
: Arm64 
Evento: task-clock:u (tipo 1, configuração 1) 
Amostras: 8647 
Contagem de eventos: 8647000000 
 
Overhead Shared Object Pid 
27,69% /system/lib64/libhwui.so 31183
17,32% /apex/com.android.art/lib64/libart.so 31183 
9,06% /apex/com.android.runtime/ lib64/bionic/libc.so 31183 
8,60% /vendor/lib64/egl/libGLES_mali.so 31183 
8,50% /system/framework/arm64/boot-framework.oat 31183 
4,75% /data/ app/~~3WfX5_4-OAPL17xSEBkRfg==/com.afmobi.boomplayer-yFLZq2TqjDUJV1OB-um-UQ==/oat/arm64/base.odex 31183
3,05% /system/framework/arm64/boot.oat 31183 
2,67% /system/lib64/libandroidfw.so 31183  
2,58% [cache do aplicativo JIT] 31183
1,78% /system/lib64/libgui.so 31183 
1,58% /data/app/~~EKnZoTKaDLH3FYfxteqUvg==/com. google.android.tricromelibrary_541411734-ozjH9V7NI4SknoCd0t2CPg==/base.apk!/lib/arm64-v8a/libmonochrome_64.so 31183
1,02% /system/lib64/libbinder.so 31183 
0,75% /apex/com.android.art/lib64/libart-compiler.so 31183 
0,68% /system/lib64/libsqlite. então 31183 
0,74% /system/lib64/libminikin. então 31183
0,73% /system/lib64/libz.so 31183 
0,53% /apex/com.android.conscrypt/lib64/libcrypto.so 31183
0,65% /system/lib64/libutils.so 31183 
0,64% /system/lib64/libjpeg.so 31183 
0,43% /apex/com.android.i18n/lib64/libicuuc.so 31183 
0,39% /apex/com.android.runtime/ bin/ligador64 31183
0,39% /system/framework/arm64/boot-core-libart.oat 31183 
0,36% /system/lib64/libc++.so 31183 
0,24% [vdso] 31183 
0,27% /system/ lib64/libandroid_runtime.so 31183
0,25% /system/framework/arm64/boot-okhttp.oat 31183 
0,22% /apex/com.android.conscrypt/lib64/libssl.so 31183 
0,21% /system/lib64/libcutils.so 31183 
0,21% /system/lib64/ libui.so 31183 
0,19% /apex/com.android.vndk.v31/lib64/libgralloctypes.so 31183 
... ..

3. Gere um relatório do gráfico de chamadas e envie-o para a saída padrão:

Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.afmobi.boomplayer 
Arch: arm64 
Evento: task-clock:u (tipo 1, configuração 1) 
Amostras: 10841 
Contagem de eventos: 10841000000 

Crianças Autocomando Pid Tid Símbolo de objeto compartilhado 
66,11% 0,00% RenderThread 31183 11235 /apex/com.android.runtime/lib64/bionic/libc .so __start_thread 
       | 
       -- __start_thread 
          |
           -- __pthread_start(void*)
              android::Thread::_threadLoop(void*) 
              android::uirenderer::renderthread::RenderThread::threadLoop() 
               |--0.01%-- [acerto na função] 
               | 
               |--99,96%-- android::uirenderer::WorkQueue::process() 
               | |--0,03%-- [acerto na função] 
               | | 
               | |--99,94%-- std::__1::__function::__func<android::uirenderer::renderthread::DrawFrameTask::postAndWait()::$_0, std::__1::allocator<android::uirenderer ::renderthread::DrawFrameTask::postAndWait()::$_0>, void ()>::operator()() (.c1671e787f244890c877724752face20) 
               | | |--0,01%-- [acerto na função]
               | | | 
               | | |--86,61%-- android::uirenderer::renderthread::CanvasContext::draw() 
               | | | |--0,11%-- [acerto na função] 
               | | | |
               | | | |--77,75%-- android::uirenderer::skiapipeline::SkiaOpenGLPipeline::draw(android::uirenderer::renderthread::Frame const&, SkRect const&, SkRect const&, android::uirenderer::LightGeometry const&, android: :uirenderer::LayerUpdateQueue*, android::uirenderer::Rect const&, bool, android::uirenderer::LightInfo const&, std::__1::vector<android::sp<android::uirenderer::RenderNode>, std ::__1::allocator<android::sp<android::uirenderer::RenderNode> > > const&, android::uirenderer::FrameInfoVisualizer*)  
               | | | | |--0.
               | | | | |
               | | | | |--58,87%-- android::uirenderer::skiapipeline::SkiaPipeline::renderFrame(android::uirenderer::LayerUpdateQueue const&, SkRect const&, std::__1::vector<android::sp<android::uirenderer ::RenderNode>, std::__1::allocator<android::sp<android::uirenderer::RenderNode> > > const&, bool, android::uirenderer::Rect const&, sk_sp<SkSurface>, SkMatrix const&) 
               | | | | | | 
               | | | | | |--86,22%-- android::uirenderer::skiapipeline::SkiaPipeline::renderFrameImpl(SkRect const&, std::__1::vector<android::sp<android::uirenderer::RenderNode>, std::__1 ::allocator<android::sp<android::uirenderer::RenderNode> > > const&,
               | | | | | | |--0,12%-- [acerto na função]

4. Exibir diagrama de chama

Para exibir o gráfico em degradê, primeiro precisamos registrar o gráfico de chamadas. Os gráficos em chama são exibidos na tag Flamegraph por report_html.py . Você também pode clicar duas vezes diretamente em inferno.bat para exibir o gráfico em degradê.

Também podemos construir gráficos em degradê usando GitHub - brendangregg/FlameGraph: Stack trace visualizador . Por favor, certifique-se de ter o perl instalado.

$ git clone https://github.com/brendangregg/FlameGraph.git 
$ python report_sample.py --symfs binary_cache >out.perf 
$ FlameGraph/stackcollapse-perf.pl out.perf >out.folded 
$ FlameGraph/flamegraph.pl fora.dobrado >a.svg

Você pode abri-lo com um navegador e ver o gráfico em degradê analisado da seguinte maneira:

  • No gráfico em chama acima, você pode ver o que o netd está executando, para que possa ser entregue aos colegas do netd para continuar o rastreamento.

O eixo y representa a pilha de chamadas, com cada nível sendo uma função. Quanto mais profunda a pilha de chamadas, maior será a chama, com a função sendo executada no topo e sua função pai abaixo.
O eixo x representa o número de amostras. Se uma função ocupa uma largura maior no eixo x, significa que ela foi amostrada mais vezes, ou seja, demora mais para ser executada. Observe que o eixo x não representa o tempo, mas todas as pilhas de chamadas mescladas e organizadas em ordem alfabética.
O gráfico em degradê serve para ver qual função de nível superior ocupa a maior largura. Sempre que há um “platô”, significa que a função pode apresentar problemas de desempenho.
As cores não têm nenhum significado especial, pois o gráfico em degradê indica o quão ocupada a CPU está, portanto, geralmente são escolhidas cores quentes.

Para obter informações detalhadas sobre o uso de gráficos de chama, consulte Como ler gráficos de chama? -Blog de Ruan Yifeng

6. Dicas e truques

Se você está apenas começando com o Simpleperf, aqui estão alguns comandos particularmente úteis que você pode tentar. Para obter mais comandos e opções, consulte Referência de comandos e opções do Simpleperf .

1. Encontre a biblioteca compartilhada que leva mais tempo de execução

Você pode executar este comando para ver quais arquivos .so ocupam a maior porcentagem do tempo de execução (com base nos ciclos da CPU). É uma boa opção executar esse comando primeiro ao iniciar uma sessão de criação de perfil.

relatório simpleperf --sort dso

exemplo:

Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data 
Arch: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 3294 
Contagem de eventos: 1193555038 

Overhead Sample Shared Object 
57,18% 2114 [kernel.kallsyms] 
8,01% 225 /system/lib64/libhwui.so 
7,16% 192 /apex/com.android.runtime/lib64/bionic/libc.so 
5,96% 169 /vendor/lib64/egl/libGLES_mali. então 
4,73% 125 /apex/com.android.art/lib64/libart.so 
4,55% 128 /system/framework/arm64/boot-framework.oat 
3,84% 96 /system/lib64/libgui.so  
1,39% 44 /system/ framework/arm64/boot.oat 
1,06% 28 /system/lib64/libutils.so
0,74% 24 /system/ lib64/libbinder.so 
0,43% 12 /system/lib64/libui.so 
0,42% 10 /system/lib64/libminikin.so 
0,34% 10 /system/lib64/libandroid_runtime.so 
0,34% 10 /system/lib64/libc++.so 
0,29% 7 /apex/ com.android.vndk.v31/lib64/libgralloctypes.so 
0,27% 8 /vendor/lib64/egl/libGLES_meow.so 
0,27% 6 /system/framework/arm64/boot-mediatek-framework.oat 
0,24% 8 [cache do aplicativo JIT ] 
0,22% 7 /system/lib64/libEGL.so 
0,19% 5 /vendor/lib64/libged.so 
0,19% 6 /apex/com.android.vndk.v31/lib64/libhidlbase.so 
0,18% 4 desconhecido 
0,16% 5 / system/lib64/libcutils.so
0,15% 2 /apex/com.android.i18n/lib64/libicuuc.so 
0,15% 5 /system/framework/arm64/boot-core-libart.oat 
...............

2. Encontre a função com maior tempo de execução

Depois de identificar a biblioteca compartilhada que está demorando mais tempo de execução, você pode executar este comando para ver a porcentagem de tempo gasto na execução das funções do arquivo .so.

relatório simpleperf --dsos biblioteca.so --sort símbolo

exemplo:

simpleperf E command.cpp:59] Opção desconhecida -dsos. Experimente o `relatório de ajuda do simpleperf`. 
1|TECNO-KI7:/ # relatório simpleperf -i /data/perf.data --dsos [kernel.kallsyms] --sort símbolo 
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data /perf.data 
Arco: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 2114 
Contagem de eventos: 682442263 

Símbolo de sobrecarga 
8,22% _raw_spin_unlock_irqrestore 
6,87% __blockdev_direct_IO 6,72 
% get_user_pages_fast 
6,61% dio_bio_complete 4,13 
% memblock_ start_of_DRAM 3,97 
% el0_da 
3,71% blk_queue_split 
3,39 % iov_iter_fault_in_readable 
2,72% _raw_spin_unlock_irq
2,30% fscrypt_mergeable_bio 
2,29% el0_svc_common 
2,23% free_unref_page_list 
2,02% queue_work_on 
1,98% mod_delayed_work_on 
1,83% blk_crypto_submit_bio 
1,79% clear_page 
1,68% _mtk_btag_pidlog_set_pid 
1,47 % get_page_from_freelist 
1,35% f2fs_is_valid_blkaddr 
1,18% fscrypt_generate_dun 
1,02% __save_stack_trace 0,97% 
pagecache_get_page 
0,95% __handle_speculative_fault 0,82 
% depot_save_stack 
0,80% f2fs_map_blocks 
0. 73% __rcu_read_unlock 
0,67% __pi_memset 
0,64% f2fs_wait_on_block_writeback 
0,56% __rcu_read_lock
0,54% kmem_cache_alloc

3. Encontre a porcentagem de tempo gasto em um tópico

O tempo de execução em um arquivo .so pode ser distribuído entre vários threads. Você pode executar este comando para ver a porcentagem de tempo gasto por cada thread.

relatório simpleperf --sort tid,comm

exemplo:

Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data 
Arch: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 3294 
Contagem de eventos: 1193555038 

Overhead Tid Command 
42.01 % 12182 Thread-4 
29,48% 11834 RenderThread 
16,96% 10167 com.andromeda.androbench2 
6,04% 11853 mali-cmar-backe 
2,70% 11876 fichário:10167_4 
1,24% 11854 ged-swd 
0,67% 11844 mali-mem-purge 
0,62% 12087 aglutinante: 10167_6 
0,26% 11968 fichário:10167_2 
0,01% 11820 Conjunto de threads Jit 
0,00% 11824 FinalizerWatchd 
0,00% 11859 Conclusão da GPU

4. Porcentagem de tempo gasto na localização do módulo de objeto

Depois de encontrar os threads que levam a maior parte do tempo de execução, você pode usar este comando para isolar os módulos de objeto que levam o maior tempo de execução nesses threads.

relatório simpleperf --tids threadID --sort dso

exemplo:

Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data 
Arch: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 1457 
Contagem de eventos: 501433272 

Overhead Shared Object 
96,72 % [kernel.kallsyms] 
2,80% /apex/com.android.runtime/lib64/bionic/libc.so 
0,33% /apex/com.android.art/lib64/libart.so 
0,08% /vendor/lib/modules/memfusion .ko 
0,07% /system/lib64/libutils.so

5. Compreenda a correlação das chamadas de função

O gráfico de chamadas fornece uma representação visual dos rastreamentos de pilha registrados pelo Simpleperf durante a criação de perfil de uma sessão.

Você pode usar o comando report -g para imprimir um gráfico de chamadas para ver quais funções são chamadas por outras funções. Isso pode ajudar a determinar se uma função em si é lenta ou se uma ou mais funções que ela chama são lentas.

Você também pode usar o script Python report.py -g para iniciar uma ferramenta interativa que exibe funções. Você pode clicar em cada função para ver o tempo gasto por suas subfunções.

relatório simpleperf -g

exemplo:

TECNO-KI7:/ # simpleperf report -g 
simpleperf E record_file_reader.cpp:83] falhou ao abrir o arquivo de registro 'perf.data': Arquivo ou diretório não encontrado 
1|TECNO-KI7:/ # simpleperf report -i /data/perf .data -g 
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data 
Arch: arm64 
Evento: cpu-cycles (tipo 0, configuração 0) 
Amostras: 3294 
Contagem de eventos: 1193555038 

Autocomando infantil Pid Tid Símbolo de objeto compartilhado 
3,93% 3,93% Thread-4 10167 12182 [kernel.kallsyms] __blockdev_direct_IO
3,84% 3,84% Thread-4 10167 12182 [kernel.kallsyms] get_user_pages_fast 
3,78% 3,78% Thread-4 10167 12182 [kernel.kallsyms] dio_bio_complete 
2,55% 2,55% mali-cmar-backe 10167 11853 [kernel. kallsyms] _raw_spin_unlock_irqrestore 
2,36% 2,36 % Thread-4 10167 12182 [kernel.kallsyms] memblock_start_of_DRAM 
2,27% 2,27% Thread-4 10167 12182 [kernel.kallsyms] el0_da 
2,12% 2,12% Thread-4 10167 12182 [kernel.kallsyms] blk_queue_split
1,94% 1,94% Thread-4 10167 12182 [kernel.kallsyms] iov_iter_fault_in_readable 
1,31% 1,31% Thread-4 10167 12182 [kernel.kallsyms] fscrypt_mergeable_bio 
1,27% 1,27% Thread-4 10167 12182 [ kernel.kallsyms] free_unref_page_list 
1,15% 1,15% RenderThread 10167 11834 [kernel.kallsyms] queue_work_on 
1,15% 1,15% Thread-4 10167 12182 /apex/com.android.runtime/lib64/bionic/libc.so memset 
1,13% 1,13% Thread-4 10167 12182 [kernel.kallsyms] mod_delayed_ trabalhando_em
1,05% 1,05% Thread-4 10167 12182 [kernel.kallsyms] blk_crypto_submit_bio 
1,02% 1,02% Thread-4 10167 12182 [kernel.kallsyms] clear_page 
1,01% 1,01% RenderThread 10167 11834 [kernel.kallsyms] _raw_spin_unlock_irqrestore 
0,96% 0,96% Tópico-4 10167 12182 [kernel.kallsyms] _mtk_btag_pidlog_set_pid 
0,77% 0,77% Thread-4 10167 12182 [kernel.kallsyms] f2fs_is_valid_blkaddr 
0,76% 0,76% RenderThread 10167 11834 /apex/com.android .runtime/lib64/bionic/libc.so __vfprintf
0,70% 0,70% RenderThread 10167 11834 [kernel.kallsyms] _raw_spin_unlock_irq 
0,68% 0,68% Thread-4 10167 12182 [kernel.kallsyms] fscrypt_generate_dun 
0,67% 0,67% Thread-4 10167 12182 [ kernel.kallsyms] get_page_from_freelist 
0,64% 0,64% RenderThread 10167 11834 [kernel.kallsyms] el0_svc_common 
0,62% 0,62% Thread-4 10167 12182 [kernel.kallsyms] _raw_spin_unlock_irqrestore
0,58% 0,58% Thread-4 10167 12182 [kernel.kallsyms] __save_stack_trace 
0,55% 0,55% Thread-4 10167 12182 [kernel.kallsyms] pagecache_get_page 
0,54% 0,54% com.andromeda.androbench2 10167 1016 7 /apex/com.android.art/ lib64/libart.so ExecuteNterpImpl 
0,51% 0,51% Thread-4 10167 12182 [kernel.kallsyms] __handle_speculative_fault 
0,46% 0,46% Thread-4 10167 12182 [kernel.kallsyms] f2fs_map_blocks
0,45% 0,45% RenderThread 10167 11834 /apex/com.android.runtime/lib64/bionic/libc.so scudo::Allocator<scudo::AndroidConfig, &(scudo_malloc_postinit)> 
rigin, unsigned long, bool) 
0,44% 0,44% RenderThread 10167 11834 /system/lib64/libgui.so @plt 
0,41% 0,41% Thread-4 10167 12182 [kernel.kallsyms] depot_save_stack 
0,36% 0,36% Thread-4 10167 12182 [kernel.kallsyms] f2fs_wait_on_block_writeback 0. 36% 0,36 
% Rosca-4 10167 12182 [kernel.kallsyms] _raw_spin_unlock_irq
0,34% 0,34% Thread-4 10167 12182 [kernel.kallsyms] __rcu_read_unlock 
0,34% 0,34% com.andromeda.androbench2 10167 10167 [kernel.kallsyms] _raw_spin_unlock_irq 
0,32% 0,32% Thread-4 10167 12182 [kernel.kallsyms] __pi_memset 
0,31% 0,31 % Thread-4 10167 12182 [kernel.kallsyms] kmem_cache_alloc 
0,31% 0,31% com.andromeda.androbench2 10167 10167 /apex/com.android.art/lib64/libart.so artAllocStringFromCharsFromCodeRegionTLAB
0,26% 0,26% mali-cmar-backe 10167 11853 [kernel.kallsyms] el0_svc_common 
0,26% 0,26% RenderThread 10167 11834 /apex/com.android.runtime/lib64/bionic/libc.so write 
0,25% 0,25% Thread-4 101 67 12182 [kernel.kallsyms] pte_map_lock 
........

6. Obtenha informações brutas do contador de eventos no programa ou sistema com perfil

simpleperf stat é usado para obter informações brutas do contador de eventos dentro do programa ou sistema com perfil. Passando opções, podemos escolher quais eventos usar, qual processo/thread monitorar, quanto tempo monitorar e o intervalo entre prints.

Estatísticas do contador de desempenho: 

# contagem event_name # contagem / tempo de execução 
    17.839.958.825 ciclos de CPU # 1,758283 GHz 
     6.411.685.476 ciclos paralisados-frontend # 632,274 M/s 
     5.413.391.502 ciclos paralisados-backend # 534,113 M/s 
    11.755, 131.810 instruções # 1.160 G/s 
     1.409.829.788 ramificações instruções # 139,262 M/seg 
       171.458.771 falhas de ramificação # 16,946 M/seg 
  10070,704634(ms) relógio de tarefa # 1,006817 cpus usado 
             7.210 trocas de contexto # 716.330 /seg 
            94.430 falhas de página # 9,387 K/seg 

Tempo total de teste: 10,002513 segundos.

7. Documentos de referência

[Simpleperf] Análise de CPU Android, ferramenta de otimização de desempenho_android perf_Yngz_Miao's blog-blog CSDN

Série quatro de ferramentas de perfil: blog de simpleperf_old_man-blog CSDN

Analisando desempenho de código nativo usando Simpleperf | WolfcsTech

Como ler gráficos em chama? -Blog de Ruan Yifeng

Introdução ao Simpleperf | WolfcsTech

Simpleperf | AndroidNDK | Desenvolvedores Android

Documentação de referência de comandos e opções do Simpleperf | Android NDK | Desenvolvedores Android

Acho que você gosta

Origin blog.csdn.net/weixin_47465999/article/details/129636331
Recomendado
Clasificación