Avaliação de Desempenho de Aplicativos Android*

por Tuan H. Bui

Visão geral

Para se otimizar um aplicativo e melhorar a experiência do usuário, é importante conhecer a exigência de desempenho do aplicativo em uma plataforma específica. No sistema operacional Linux*, pode-se utilizar o vmstat para monitorar vários aspectos de desempemho de um aplicativo, como seu consumo de memória, a demanda de CPU e de I/O. O Windows Task Manager* fornece uma capacidade semelhante para o sistema operacional Windows*. Neste artigo, discutimos como obter dados de desempenho semelhantes para o sistema operacional Android*.

Discussão

O Android* é essencialmente um sistema operacional Linux*, portanto, fornece dados de desempenho similares. A obtenção desses dados é um pouco difícil, já que o modelo de uso de telefone/tablet permite que apenas um aplicativo seja executado em primeiro plano.

O primeiro passo para monitorar o desempenho de um aplicativo rodando em Android* é executar utilitários de monitoramento de desempenho enquanto o aplicativo está executando uma carga de trabalho. Por exemplo, queremos monitorar o desempenho de um aplicativo de reprodução de vídeo para entender por que o aplicativo não está sendo executado na frequência necessária. Como nosso aplicativo de interesse, o vídeo player neste caso, está sendo executado em primeiro plano, precisamos encontrar uma forma alternativa de monitorar seu desempenho enquanto o vídeo player estiver em execução. Uma maneira de fazer isso é criar um serviço Android* que seja executado continuamente em segundo plano e que registre os dados de desempenho em um arquivo a ser examinado posteriormente. A abordagem mais simples é utilizar o utilitário Android* Debug Bridge (adb). O Android* ADB fornece um shell de depuração para o sistema operacional Android* através do cabo USB ou através de uma porta TCP/IP. Utilize o procedimento abaixo para ativar a depuração adb através de TCP/IP utilizando uma rede sem fio.

  1. Ative a depuração USB no painel de controle do Android*.
  2. Conecte o dispositivo ao host através de um cabo USB. Se estiver utilizando um host Windows*, você provavelmente precisará obter o driver do dispositivo USB do fabricante do dispositivo. Um host Linux* geralmente não precisa de um driver de dispositivo especial.
  3. Verifique se o dispositivo pode ser visto pelo host através do comando 'adb devices'. O comando irá devolver uma lista de dispositivos conectados ao host.
  4. Ative a depuração TCP/IP através do comando 'adb tcpip 5555'. Este comando instrui o adb para reiniciar e conectar à porta 5555 para receber mensagem de conexão adb.
  5. Desconecte o cabo USB e reconecte ao dispositivo através do comando 'adb <endereço_ip_do_dispositivo>'.
Uma vez conectado através do adb, o usuário terá acesso a um shell Unix que poderá ser utilizado para executar em segundo plano vários comandos de monitoramento, como 'top' e 'vmstat', enquanto o aplicativo de interesse estiver em execução na tela principal do dispositivo. Tenha em mente que a execução de outros comandos em paralelo ao aplicativo pode degradar o desempenho do aplicativo. O comando 'top', por exemplo, é bastante intenso na utilização da CPU e deve ser utilizado com cuidado. A melhor forma de monitorar o desempenho com o mínimo de sobrecarga é simplesmente coletar os dados produzidos pelo sistema operacional em intervalos regulares e armazená-los em um arquivo a ser processado após o aplicativo ter finalizado sua execução. O Android*, assim como o Linux*, fornece a maioria das estatísticas de desempenho no arquivo de sistema armazenado em /proc. Os dados de desempenho estão armazenados em /proc/stat. Para monitorar o desempenho do sistema em intervalos regulares de 5 segundos, basta utilizar um shell script semelhante a este:

while :
do
	echo Date: `date +”%Y-%m-%d %H:%M:%S”`
	cat /proc/stat >> /data/local/tmp/myvmstat.out
	sleep 5
done


A seguir estão dois exemplos de /proc/stat capturados em intervalos de 5 segundos enquanto o Android* Media Player está reproduzindo um vídeo de 720p H264 em um tablet Motorola Xoom* 1. Os dados foram importados para uma planilha para facilitar a leitura.



Há muitos dados incluídos no arquivo /proc/stat. A informação mais importante está na primeira linha reportando a soma de todas as atividades da CPU. Cada linha subsequente que começa com 'cpuN' reporta as atividades daquela CPU em particular. Podemos ver que o dispositivo do exemplo acima possui dois processadores. O significado de cada campo é explicado a seguir:

1 * Outros nomes e marcas podem ser considerados como de propriedade de terceiros



Unidades de tempo são dadas em USER_HZ, geralmente um centésimo de segundo. Valores numéricos nestas estatísticas estão acumulados desde a inicialização do sistema. Para obter os dados de desempenho para cada intervalo de tempo, é necessário calcular a diferença entre os dados capturados no início e no final de cada intervalo.

User: tempo gasto executando processos no modo de usuário
Nice: tempo gasto executando processos no modo usuário ”niced”. Processos ”niced” são processos em execução na prioridade que não seja prioridade padrão predefinida
System: tempo gasto executando no modo kernel ou no modo de supervisão
Idle: tempo de execução de processo ocioso. Nenhum processo executável está disponível
Iowait: tempo de espera de conclusão de I/O
Irq: tempo atendendo interrupções
Softirq: tempo atendendo interrupções de software
Steal, Guest Time, Guest Nice Time: tempo gasto em guess OS virtualizados. Geralmente estes valores estão zerados no Android*

O restante dos dados reportados em /proc/stats estão descritos abaixo:

Intr: número de interrupções tomadas pelo sistema. A primeira coluna após a marca 'intr' corresponde ao número total de interrupções tomadas desde a reinicialização do sistema. Os valores nas colunas subseqüentes indicam o número de interrupções tomadas para a interrupção indicada pelo número da coluna, a partir da interrupção 0
Ctxt: número de trocas de contexto tomadas desde a reinicialização do sistema
Btime: tempo de inicialização do sistema dado como o deslocamento em segundos desde 1 de janeiro de 1970 GMT
Processes: número de processos criados pelo sistema desde a sua inicialização
Procs running: número de processos em execução
Procs blocked: processos bloqueados aguardando conclusão de I/O
Softirq: número total de softirq processadas. Softirq são interrupções de software não urgentes

A tabela abaixo mostra a diferença entre os dois exemplos de dados mostrados anteriormente. A coluna sum mostra a soma total de unidades de tempo gasto em tarefas diversas. A coluna CPU Util é a soma de todas as tarefas não ociosas. A linha logo abaixo de cada CPU mostra os mesmos dados em percentagem do tempo total gasto. Observe que o tempo total gasto em várias tarefas é da ordem de 5 segundos. Como há dois processadores no sistema, o tempo total de CPU disponível para cada exemplo é 2x5 = 10 segundos.



Para uma carga de trabalho de execução razoavelmente longa, como, por exemplo, reprodução de vídeo, podemos formar um gráfico de tempo mostrando a utilização da CPU da carga de trabalho ao longo do tempo. Estudando esse gráfico de tempo é possível identificar diferentes fases onde a carga de trabalho pode estar excessiva para os recursos do processador. A figura 1 abaixo mostra esse gráfico de tempo para uma carga de trabalho gráfica orientada. Observamos que a utilização máxima da CPU atingida pela carga de trabalho é de apenas 50%. Esta é uma indicação de que a carga de trabalho só foi capaz de utilizar uma CPU. Se fosse importante acelerar essa carga de trabalho, isso poderia ser útil para encontrar maneiras de utilizar a segunda CPU.



Figura 1 - Utilização da CPU An3DBenchXL

A utilização da CPU não mostra tudo sobre o desempenho. Processadores modernos normalmente podem operar em várias frequências diferentes, chamadas pstates. O sistema operacional pode mudar as frequências de operação do processador para minimizar o consumo de energia e aumentar a duração da bateria, no caso de dispositivos portáteis. 

A figura 2 abaixo mostra a utilização da CPU juntamente com a freqüência média da operação do processador do mesmo tablet reproduzindo o mesmo videoclipe codificado em 720p H264 e 360p H264. Como mostram os dados, a reprodução de vídeo 720p H264 é muito mais intensiva no uso de recursos do que a diferença entre a utilização da CPU pode indicar. A decodificação de vídeo 720p H264 não só requer a utilização da CPU 4X, como também a execução do processador em freqüência maior que ~ 2.4X.



Figura 2 - Desempenho de reprodução de vídeo

O Android* reporta sua freqüência de operação do processador ou o pstate no arquivo /sys/devices/system/cpu/cpuX/cpufreq/stats/time_in_state. O script abaixo está modificado para incluir a coleta de dados do processador pstate. 
while :
do
	echo Date: `date +”%Y-%m-%d %H:%M:%S”`
	cat /proc/stat >> /data/local/tmp/myvmstat.out
	echo CPU0 Pstate Residency
	cat /sys/devices/cpu/cpu0/cpufreq/stats/time_in_state
	echo CPU1 Pstate Residency
	cat /sys/devices/cpu/cpu1/cpufreq/stats/time_in_state
	sleep 5
done


Os dados obtidos do processador pstate do Motorola Xoom são mostrados abaixo.

CPU0 PState Residency
216000 4356448
312000 400626
456000 559897
608000 398231
760000 92081
816000 0
912000 0
1000000 1485891


Cada par representa uma freqüência pstate em KHz e tempo passado, em centésimos de sgundo, naquele estado desde que o sistema iniciou o boot. O número de pstate disponível é diferente para cada processador. Nessa caso, o processador NVIDIA Tegra2 que equipa o Motorola Xoom tem 8 possíveis pstates variando de 216 MHz até 1GHz.

Aplicando-se a mesma técnica utilizada para calcular a utilização da CPU, podemos calcular a percentagem de tempo que o processador gastou em cada pstate, para um dado intervalo de amostragem. Podemos também derivar uma frequência média para o mesmo intervalo, calculando uma soma ponderada da frequência pstate e a porcentagem de tempo gasto nesse pstate. Esses dados foram obtidos e mostrados na Figura 1.

Sumário

Utilizando-se o adb e aproveitando-se a infraestrutura de desempenho existente que o Android* herdou do Linux, podemos obter novos conhecimentos sobre as características de desempenho do aplicativo Android*. Tais conhecimentos podem ser utilizados para otimizações dos aplicativos e para aprimorar a experiência do usuário, reduzindo o consumo de energia.