×
Namespaces

Variants
Actions
(Redirected from Como otimizar em Java ME)

Dicas gerais para se otimizar código Java ME

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

Artigo
Tradução:
Por maiconherverton
Última alteração feita por lpvalente em 08 Mar 2014

Este artigo fala sobre alguns tópicos gerais a se considerar para se otimizar código em Java ME.

Existem dois fatores-chave para considerar quando você quer otimizar a sua aplicação Java ME

  • Performance
  • Tamanho

Você deve atrasar a otimização até o último minuto, depois de criar as principais características da sua aplicação. Porém, tenha em mente todos os fatores-chave ao longo do ciclo de desenvolvimento a fim de evitar grandes mudanças no final.

Contents

Desempenho

Regra número um para que o desempenho "seja simples" , não tente criar sistemas mais complexos para o seu celular. Lembre-se que as pessoas querem aplicativos/games rápidos e fáceis de usar. Com isto em mente tenha em conta as seguintes questões:

Threads

  • Utilize apenas uma thread no aplicativo, ou seja, evite várias threads. Muitos dispositivos não podem lidar com muitas threads. Threads inerentes a conexão de rede é a única exceção para a criação de um nova thread.
  • Uso minimizado de sincronia, é caro em dispositivos além e é muito comum criar códigos sincronizados ruims. Sincronizar run com paint () e keyPressed () não tem problemas.
  • Evite o uso da classe Timer, uma Thread extra é criada para cada um.
  • Crie uma thread no método startApp() e reutilize-a.
  • Não use o método Display.callSerially(), é muito lento e com bugs em muitos dispositivos. Uma nova Thread é criada na maioria das implementações
  • Evite utilizar o método serviceRepaints() em dispositivos legados quando o desempenho se tornar um problema
  • Talvez seja necessário garantir a segurança da thread (thread em segundo plano e discussão do sistema) se serviceRepaints() não é usado

Um exemplo para a estrutura de base para sua aplicação:

public void startApp() {
animationThread = new Thread(this);
}
 
public void run() {
init();
while(!exitApp) {
updateModel(); // sua app lógica
repaint();
serviceRepaint();
sleep(50); // sufoco em dispositivos lentos
}
}

Sistemas Callbacks

Você deve tratar com cuidado os retornos de chamada de sistema, eles são chamados pela thread do sistema. Eles não devem bloquear e devem retornar o mais rapidamente possível para evitar problemas de performance da VM. Crash na aplicação pode acontecer se o retorno não for o mais rápido possível. Aqui está uma lista com os retornos do sistema mais comum:

  * paint
  * keyPressed
  * startApp/pauseApp
  * hideNotify/showNotify
  * MIDlet constructor  

Abaixo você tem um mau exemplo de um sistema de chamada de retorno:

public void paint(Graphics g) {
updateModel();
drawBackground(g);
drawForeground(g);
}
 
public void run() {
while(!exitApp) {
repaint();
serviceRepaints();
sleep(50);
}
}

Como você deve ter notado, estamos atualizando nosso modelo, uma operação cara, durante a pintura de eventos do sistema. Devemos mudar o nosso código para o seguinte:

public void paint(Graphics g) {
drawBackground(g);
drawForeground(g);
}
 
public void run() {
while(!exitApp) {
updateModel(); // melhor fazê-lo aqui
repaint();
serviceRepaints();
sleep(50);
}
}

Diferentes dispositivos - Diferentes Desempenhos

Há diferenças enormes entre dispositivos atuais e mais antigos. Os dispositivos podem ser muito mais rápido ou mais lento do que o esperado, portanto você não pode assumir o desempenho.

Se você tem a sua lógica de jogo baseada na taxa de quadros, isso pode resultar em jogo totalmente "jogável". Você deveria basear seu jogo no modelo em tempo real, como o exemplo a seguir:

public void updateModel() {
curTime = System.currentTimeMillis();
elapsedTime = curTime – prevTime;
// usando a lógica elapsedTime para seu app aqui
prevTime = curTime;
}
 
public void run() {
while(!exitApp) {
updateModel();
repaint();
serviceRepaints();
sleep(50);
}
}

Outro aspecto a ser levado em consideração é o desempenho de algumas APIs. Nesta caso, algumas chamadas são mais lentas do que outras:


  • drawString(), substituir com fonte de gráficos
  • drawArc(), Vector, Hashtable, substituir com a própria implementação
  • drawImage(), substituir as imagens de grandes dimensões com uma série de imagens menores para alguns dispositivos

Outra coisa a tratar com cuidado é a detecção de colisão. Esta deve ser calculada entre os quadros para evitar problemas em dispositivos de baixa taxa de quadros.

Desativar certos recursos no dispositivo lento através da entrada .JAD. Por exemplo, se "tree.png" não existe, não desenhar o sprite árvore

I/O

A utilização de RMS solicitando getResourceAsStream é muito lenta. Tome a seguinte consideração quando utilizá-los:

RMS

  • Leia todo o registro em um buffer
  • Em seguida, leia do buffer
  • Da mesma forma, escrever para um buffer interno, em seguida, escrever o buffer para um registro

getResourceAsStream()

  • Extremamente lento em alguns aparelhos (mais lento que o de 20 bytes por segundo)
  • Classe de carregamento é muito mais rápida nesses dispositivos
  • Solução: armazenamento de dados em arquivos separados da classe em vez de usar recursos. Isso pode resultar em pouco mais carga de aplicação

Geral

Aqui algumas coisas que "LITERALMENTE" fazem grandes diferenças:

  • Evite a criação de objetos desnecessários / alocação de memória.
  • Reduzir, reutilizar, reciclar as instâncias do objeto que você usa
  • Não fazer concatenações de grandes sequencias de Strings usando "+", use a classe StringBuffer
  • Imagens grandes é melhor diminuir e ciar várias pequenas, criando um cache de imagens
  • Evitar a criação desnecessária de loops / eliminação de variáveis dentro de loops
  • Use declarações switch-case, ao invés de blocos if, que são traduzidos para bytecodes Java mais rápido
  • Usar variáveis públicas diretamente em vez de utilizar métodos get/set.
  • Defina variáveis como null quando você não precisar mais delas
  • Garbage Collector, chamada com frequência e explicitamente em alguns dispositivos. Cuidado com a não-compactação GC
  • Use variáveis locais em vez de variáveis globais quando puder. As variáveis locais são mais rápidas e utilizam menos bytecode

Dê uma olhada no seguinte exemplo:

for(y = 0; y < oriHeight; y++) {
for(x = 0; x < oriWidth / 2; x++) {
int idx1 = y * oriWidth + x;
int idx2 = (y + 1) * oriWidth – 1 - x;
curPixel = buf[idx1];
buf[idx1] = buf[idx2];
buf[idx2] = curPixel;
}
}

Se fizermos a criação de índice fora dos circuitos como este:

  int idx1;
int idx2;
for(y = 0; y < oriHeight; y++) {
idx1 = y * oriWidth;
idx2 = (y + 1) * oriWidth – 1;
for(x = 0; x < oriWidth / 2; x++) {
curPixel = buf[idx1];
buf[idx1] = buf[idx2];
buf[idx2] = curPixel;
idx1++;
idx2--;
}
}

Pode economizar alguns segundos em um dispositivo real!

Tamanho

A restrição de tamanho para aplicações Java ME vem de duas fontes:

  • Capacidade de dispositivos: alguns dispositivos só aceitam aplicações de até 64 kb!
  • Limitação do Operador gateway, para evitar que os clientes parmaneçam esperando por muito tempo (e pagar muito!!) para um aplicativo de download de alguns operadores limitam o tamanho máximo da aplicação (normalmente em torno de 300kb)

Tamanho de limite no dispotiviso para o JAR tem melhorado continuamente ao longo do tempo, mas nunca é o suficiente para desenvolvedores! Então aqui algumas dicas para ajudá-lo:

  • Minimizar o número de classes, evitar POO (se possível), cada classe/interface contribui com pelo menos 250 bytes de sobrecarga após a compressão. Pode sair com 2 classes: uma MIDlet de classe e uma classe Canvas.
  • Use um Obfuscador
  • Otimizar Imagens
  • Alterar o algoritmo ZIP, JAR utilitário JDK não é o ideal. Use open source, freeware ou alternativas comerciais, onde o número de passos são configuráveis, mas cuidado com a compatibilidade do dispositivo.

Obfuscador

O que ele faz? A finalidade original é tornar a engenharia reversa muito difícil por:

  • Elimina pacotes (ou seja, sempre utiliza um pacote padrão)
  • Os nomes dos métodos são renomeados
  • Remove o código utilizado

Mas tem o efeito colateral agradável de se criar arquivos de tamanho menor (e também um pouco mais rápido). Alguns deles também realizam a otimização de bytecode. Eles podem, tipicamente, reduzir o tamanho do arquivo em 30-50% Há muitos bom obfuscadores Open source (Proguard, Retroguard) e muitos outros produtos comerciais.

Imagens

Quais são os problemas?

  • Não compressível
  • Cada arquivo PNG contém mais de menos o mesmo cabeçalho e rodapé
  • Flipped imagens, transformou as imagens em dispositivos MIDP 2.0 são ou muito lentas ou não funcionam. Não é suportada nos dispositivos MIDP 1.0. Deve incluir versão de sprites na hora de compilar isso pode dobrar ou quadruplicar o tamanho

Aqui estão as soluções:

  • Use como um otimizador PNG optipng ou [pngcrush http://pmt.sourceforge.net/pngcrush/]
  • Como alternativa, não comprimir o conteúdo da imagem - PNG tamanhos maiores, mas menor antes da compressão no final
  • Combine PNGs múltiplos em um pacote de único recurso ou uma imagem grande. Torna-se mais compressível e anula o cabeçalho e rodapé
  • Imagens Invertidas
  • Flip imagens dinamicamente em tempo de execução
  • Potencialmente um tradeoff entre performance de tamanho e JAR
  • Reduzir a profundidade de cor (se possível)

Veja também: How to optimize PNGs to reduce JAR size (Inglês)

This page was last modified on 8 March 2014, at 20:32.
75 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×