Este documento discute técnicas para otimizar o desempenho de aplicativos Android, abordando tópicos como boas práticas de programação, uso de código nativo, consumo de energia e comunicação. O autor realizou experimentos para avaliar esses aspectos e conclui que código nativo pode ser até 18 vezes mais eficiente, mas aumenta a complexidade do aplicativo. Além disso, a autonomia da bateria em dispositivos móveis ainda é insuficiente e há falta de modelos para avaliar adequadamente o consumo de energia
1. Técnicas de otimização de
desempenho de aplicações
Android
Rafael Lisboa Pereira
Orientador: Prof. Dr. Arlindo Flavio da Conceição
2. Roteiro
Introdução
O sistema Android
Tópicos
Boas práticas
Uso de código nativo
Consumo de energia
Comunicação
Conclusão
3. Android
Primeira versão - 2007
SO + plataforma para dispositivos móveis
Google e Open Handset Alliance
Software livre (Apache Software License v2)
5. Motivação
Desempenho é essencial
Recursos limitados de hardware
Bateria
Pouca pesquisa
6. Objetivo
Estudar o funcionamento do Android e seus
componentes
Ponto inicial para investigações mais aprofundadas
sobre os diversos aspectos de otimização de
aplicativos Android
7. O sistema Android
Kernel Linux 2.6
Aplicações executadas na máquina virtual Dalvik
Desenvolvimento em sintaxe Java
Classes do projeto Apache Harmony
Android SDK
8.
9. Máquina virtual Dalvik
Não é uma máquina virtual Java!
Uma instância por aplicativo
Segurança entre processos
Dalvík: vilarejo de pescadores da Islândia
10. Componentes de uma aplicação
Principais:
Activity: interface com o usuário
Service: thread de execução em segundo plano
BroadcastReceiver: escuta mensagens do sistema
ContentProvider: fornece dados a outros aplicativos
Vantagem: incentiva o uso de componentes de outros
aplicativos
11. Programação Android
Linguagem Java, mas em um ambiente diferente
Máquina virtual
Interação com o usuário
Hardware
12. Boas práticas de programação
Básicos:
Não realizar tarefas desnecessárias
Sempre que possível, não usar a memória
Criação de objetos
Palavras-chave static e final para valores constantes
13. Boas práticas de programação
Versão aprimorada da sintaxe do for (for-each)
static class Foo {
int bar;
}
Foo[] mArray = ...
public void A() {
int soma = 0;
for (int i = 0; i < mArray.length; ++i) {
soma += mArray[i].bar;
}
}
public void B() {
int soma = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
soma += localArray[i].bar;
}
}
public void C() {
int soma = 0;
for (Foo a : mArray) {
soma += a.bar;
}
}
14. Boas práticas de programação
Conhecer e utilizar as bibliotecas padrão
Exemplo: System.arraycopy()
Evitar o ANR (Application Not Responding)!
Usar threads para tarefas mais longas
Tempo de resposta: máximo de 100 a 200ms
15. (Não tão) Boas práticas de programação
Melhor desempenho, mas...
Utilizar vários vetores ao invés de uma matriz
Matriz de int é um vetor de objetos (int, int)
Métodos static: chamada cerca de 20% mais rápida
Variáveis float: operações 2x mais lentas que int
Nem todo hardware implementa divisões
16. Uso de código nativo
Máquina virtual Dalvik – código intermediário (bytecode)
Android NDK – execução de funções escritas em C/C++
em modo nativo
Java Native Interface (JNI)
18. Uso de código nativo – Avaliação empírica
Resultados do experimento de latência
C:
JNIEXPORT jint JNICALL
nativeMethod(JNIEnv *env,
jobject obj) {
return 1;
}
Java:
private int dalvikMethod() {
return 1;
}
19. Uso de código nativo – Avaliação empírica
Resultados do experimento de uso de memória
C:
char A[1000][1000];
int i, j;
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
A[i][j] = 'a';
}
}
return A[999][999];
Java:
char[][] A =
new char[1000][1000];
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < 1000; ++j)
A[i][j] = 'a';
return A[999][999];
20. Uso de código nativo – Avaliação empírica
Resultados do experimento de processamento com variáveis do tipo inteiro
C:
int i = 0, j = 0;
while (i < 2000000+k) {
j = i+(i-k);
i = j-(i+k);
i++;
}
return i+k;
Java:
int i = 0, j = 0;
while (i < 2000000+k) {
j = i+(i-k);
i = j-(i+k);
i++;
}
return i+k;
21. Uso de código nativo – Avaliação empírica
Resultados do experimento de processamento com variáveis de ponto flutuante
C:
float i = 0.0, j = 0.0;
while (i < 2000000+k) {
j = i*(i+k);
j = j/(i+k);
i++;
}
return i+k;
Java:
float i = 0, j = 1;
while (i < 2000000+k) {
j = i*(j+k);
j = j/(i-k);
i++;
}
return (int)i+k;
22. Uso de código nativo – Avaliação empírica
Resultados do experimento de escrita de arquivos
C:
FILE* teste =
fopen("/sdcard/teste.native.txt",
"w+");
if (teste != NULL) {
int i;
for (i = 0; i < 5120; i++)
fputc('n', teste);
}
fclose(teste);
return 0;
Java:
File teste = new File(sdroot,
"teste.dalvik.txt");
OutputStream os =
new FileOutputStream(teste);
byte[] r = "r".getBytes();
for (int i = 0; i < 5120; i++)
os.write(r);
os.close();
return 0;
23. Uso de código nativo
Aumenta a complexidade do aplicativo
Impacto positivo na performance
Compilação
Perda de compatibilidade
24. Consumo de energia
Dispositivos móveis: poderosos!
Bateria: autonomia de 12 horas...
25. Consumo de energia – Recursos do Android
Gerenciador de bateria
API Android:
Recebimento de broadcasts
Nível da bateria
(BatteryManager.EXTRA_LEVEL)
Nível máximo da bateria
(BatteryManager.EXTRA_SCALE)
Temperatura da bateria
(BatteryManager.EXTRA_TEMPERATURE)
Voltagem da bateria
(BatteryManager.EXTRA_VOLTAGE)
26. Consumo de energia
O que consome mais energia? (Google I/O 2009)
Serviços de atualização periódica
Transferência de dados via rede (lenta)
Movimentação entre redes
27. Consumo de energia - Experimentos
1) Comparação: código nativo vs. código Dalvik
Processamento de variáveis float
2) Decaimento da carga
Ambiente:
Motorola Flipout (Android 2.1)
Bateria de 1130 mAh, 4.2 Wh, carga 100%
Display ligado (claridade em 10%)
28. Consumo de energia – Cód. Nativo & Dalvik
Dispositivo em “modo avião”
Execução em loop de cada código durante 10 minutos
Código Dalvik: 0,11% por execução
Código nativo: 0,02% por execução
29. Consumo de energia – Decaimento da
bateria
Dispositivo conectado a rede de telefonia (GSM)
Display exibindo imagem branca
Dados de consumo armazenados a cada broadcast
Decaimento linear
30. Consumo de energia
Faltam modelos adequados para avaliar o consumo de energia
Recursos fornecidos pelo sistema são insuficientes
31. Comunicação
Importante funcionalidade dos dispositivos móveis
Requer muita energia
Sujeito a tarifas
35. Comunicação
UDP possui desempenho melhor que TCP
Não há controle sobre o envio e recebimento de pacotes
Tamanho ótimo para pacotes UDP: padrão (1470)
Elevada taxa de perda de pacotes para outros tamanhos
36. Conclusão
Programação para Android
Novos conceitos de modelagem
Engenharia de software vs. desempenho
Código nativo
Até 18 vezes mais eficiente
Complexidade e incompatibilidade
Consumo de energia
Autonomia da bateria: insuficiente
Economizar...
Comunicação
Falta controle do ambiente para estudar redes de maior escala
37. Referências Bibliográficas
Google, Inc. “Android Developers”. 2010. Disponível em
http://developer.android.com. Acesso em maio de 2011.
Info Q. “Google’s Android SDK bypasses Java ME in favor of Java Lite and Apache
Harmony”. 2007. Disponível em http://www.infoq.com/news/2007/11/android-java.
Acesso em junho de 2011.
NLANR/DAST. Iperf. 2011. Disponível em http://iperf.sf.net. Acesso em junho de
2011.
NielsenWire blog. “Android Leads in U.S. Smartphone Market Share and Data
Usage”. 2011. Disponível em http://blog.nielsen.com/nielsenwire. Acesso em junho
de 2011.
Sharkey, J. “Coding for life–battery life, that is”. In: Google IO Developer Conference,
2009.
Ferreira, D.; Dey, A.; Kostakos, V. “Understanding human-smartphone concerns: A
study of battery life”. 2011.