ASP.NET Tunning

Boa noite pessoal, este post é um apanhado de dicas de como aumentar a performance de suas aplicações ASP.NET. Todas foram testadas na prática por mim no projeto do Busca Acelerada, que de tão rápido que é, o pessoal nunca acredita que é feito em ASP.NET, hehehe. Muitas das dicas são para quem programa com WebForms, pois eu não utilizo ASP.NET MVC em meus projetos. É muito provável também que você não poderá utilizar todas essas dicas devido à natureza de sua aplicação, eu uso todas, mas o Busca Acelerada é um projeto bem fora do comum mesmo, então não é parâmetro. Ou seja, nem tudo que eu disser aqui vai se aplicar ao seu caso. Sugiro usar este post em conjunto com os outros dois que tem aqui no blog sobre como aumentar o desempenho de websites.

E por último, pretendo atualizar este post periodicamente conforme for encontrado mais dicas por aí ou for descobrindo coisas novas por minha conta mesmo.

Session

Todo mundo já deve ter ouvido falar mal do uso de sessões em ASP.NET. A sessão é uma área de memória no servidor alocada para cada usuário utilizando seu sistema. Além de um tempo de expiração definido na aplicação e/ou no servidor, a sessão é “apagada” quando o usuário fecha o navegador. Como qualquer coisa salva na memória do servidor, algo extremamente concorrido e limitado, deve ser usado com parcimônia. Ou melhor, não use.

No Busca Acelerada adotamos a política de não utilizar sessão. Em casos raros utilizamos cookies na máquina do cliente ou simplesmente passamos as informações via QueryString. Para deixar de utilizar sessão, não basta não salvar dados na Session, mas sim deve marcar suas páginas com o atributo EnableSessionState=”False”, na diretiva Page. Se você tem a mania de usar sessão apenas para passar um dado de uma página para outra (um ID para editar um cliente, por exemplo), considere passar esta informação via querystring e poupe a memória do seu servidor.

View-State

A menina dos olhos do pessoal que gosta de WebForms e o terror dos webdesigners. O ViewState garante que entre um PostBack e outro, os seus dados ainda estarão persistidos, salvando e criptografando todos em um hidden field no seu HTML. Quanto mais server controls com runat=”server” você possuir em seu ASPX, maior será o tamanho do seu view-state e consequentemente o tempo de download da página. Mais que isso, processar grandes viewstates consome tempo de processamento do servidor, principalmente se você parar pra pensar que este dado é criptografado.

Aqui temos dois ajustes a serem considerados: tamanho do arquivo (e consequente tempo de download) e processamento do servidor. Eu abracei os dois e não utilizamos view-state no Busca Acelerada. Caso tenha que utilizar view-state no seu projeto, mas os campos do seu formulário não possuem dados sensíveis (i.e. sigilosos) ou sua aplicação está sobre SSL, desabilite a criptografia do Viewstate na diretiva page do seu ASPX com o atributo ViewStateEncryptionMode=”Never”. Isso irá diminuir o processamento no servidor.

Caso possa abrir mão completamente do view-state, adicione o atributo ViewStateMode=”Disabled” na diretiva Page, o que vai reduzir o tamanho do HTML gerado. Caso não possa fazer isso pois precisa manter o estado entre os Postbacks, tente reduzir o tamanho do seu ViewState com as seguintes dicas:

  • se o texto jamais é alterado via C#, jamais use uma asp:Label para exibi-lo. Prefira a tag label do HTML ou apenas escreva literalmente na página.
  • use o menor número possível de ASP Controls no seu formulário e elementos com runat=”server”
  • desabilite o viewstate para controles que você não precisa manter estado entre postbacks, como botões e repeaters por exemplo. Use a propriedade ViewStateMode do controle para desativá-lo.

Event Validation

O ASP.NET por padrão é um dos frameworks web mais seguros da atualidade. Por padrão ele já protege contra injeções de script em formulários, por exemplo. Caso você já faça a sua própria validação no lado do servidor e/ou possua outros mecanismos de proteção para isso, considere desabilitar a validação de eventos na diretiva page de suas páginas com o atributo EnableEventValidation=”False”. Note que EventValidation é completamente inútil em páginas que não possuam campos de entrada de dados.

Web.Config

Muitas são as dicas de otimização de performance que podem ser feitas diretamente no web.config. Além de várias das dicas anteriores, que podem ser feitas a nível de página ou de aplicação, tem algumas que são exclusivas deste arquivo. A saber:

  • se sua aplicação não usa nenhum tipo de autenticação, declare o authentication mode como none. Remover a tag não adianta, pois o ASP.NET assumirá o padrão como Windows, que consumirá processamento do servidor durante as requisições de página.
  • em produção, declare  para economizar processamento e memória no servidor, desabilitando o recurso do ASP.NET de registrar todos os “movimentos” dos usuários para uma melhor depuração, visto que em produção não é lugar para depuração!
  • em produção, use compilation em debug=”false”. Você notará que por padrão o web.config já possui uma tag compilation. Substitua ela por essa quando em produção, para diminuir o consumo de memória e o tempo de compilação da aplicação, definindo que não deverá manter informações para debug em memória e já dizendo exatamente a linguagem e framework de sua aplicação.
  • use sessionState em mode=”off” caso queira desabilitar a sessão para toda sua aplicação, reduzindo o consumo de memória no servidor ou  para definir várias configurações de página ao mesmo tempo.
  • use customErrors sempre como On ou RemoteOnly em produção, e aqui o motivo não é performance, mas sim segurança.

Web Services

Ao usar Webservices em sua aplicação ASP.NET, prefira pelos padrões mais modernos como o WCF e sempre que possível, faça-os sobre o protocolo REST, ao invés de SOAP. O intuito do post não é ensinar como se faz webservices de alto desempenho, mas vale lembrar que SOAP utiliza XML, o que cria arquivos maiores e processamento desnecessário nos casos em que não se precisa manter estado ou verificações de integridade. O REST é um padrão mais simples, leve e seguro se bem utilizado, como sobre SSL, por exemplo. Pense nisso, irá diminuir o tempo de comunicação com o webservice.

ASP.NET Ajax

Evite sempre que possível de utilizar o ASP.NET Ajax. Ao invés disso, prefira o uso de JQuery e suas funções load, post, getJSON, entre outras, que fazem muito bem o seu papel e removem overheads desnecessários na sua aplicação, como aumento de viewstate, por exemplo. Nem vou citar o famigerado Ajax Control Toolkit, simplesmente não use ele.

Javascript

Use Javascript sempre que possível para solucionar problemas que não envolvem segurança. Isso irá diminuir seus postbacks e aumentará a velocidade das páginas, melhorando a experiência dos usuários. Muitos desenvolvedores ASP.NET odeiam Javascript, e eu já fui um deles. Coloque na sua cabeça que é muito importante aprendê-lo principalmente para distribuir o processamento entre os usuários ao invés de acumular tudo no seu servidor, sobrecarregando-o. Frameworks como JQuery e Bootstrap ajudam bastante a romper esse estigma do Javascript e são muito produtivos.

Generic Handler

Sempre que você precisar fazer uma comunicação de um código Javascript com o banco de dados ou com algum código C# dentro da mesma aplicação, prefira o uso de Generic Handler (.ashx) a qualquer outro método. O Generic Handler permite tratar requisições feitas de qualquer fonte (JS por exemplo) e permite retornar qualquer tipo de dado sem toda a pilha de execução de uma página ASP.NET tradicional. Quer carregar uma tabela do banco via JS? Chama um generic handler retornando uma lista de JSON. Quer salvar um dado JS no banco ou na sessão? Chama um Generic handler. Quer fazer uma página que a partir de um ID da URL baixa um arquivo? Chama um Generic handler, e por aí vai.

Para retorno de objetos a partir de um Generic Handler, sugiro o uso de JSON e somente em último caso XML, por ser mais pesado.

Postbacks

Evite postbacks sempre que possível. Postbacks geram processamento no servidor, sem contar o tempo dispendido trafegando dados pela rede. Quando postbacks são algo inevitável (botão de salvar formulário, por exemplo), tenha certeza de que no evento Page_Load da sua página existe uma verificação “Page.IsPostback == false” ou similar, para garantir que a página inteira não será carregada novamente para logo em seguida ter a ação do botão executada. Lembre-se que no ciclo de vida de uma página ASP.NET, o Page_Load acontece antes do que qualquer evento Click.

Output-Cache

Essa dica eu não uso, mas sei de vários casos em que foi utilizado e deu grandes melhorias. Eu não uso pelo simples fato de que memória é um recurso valioso para mim e processamento eu tenho sobrando no servidor, ou seja, a principal vantagem do Output-Cache, que é reduzir o processamento das páginas ASPX em páginas HTML tradicionais para serem exibidas no browser, não me serve pra muita coisa, além do fato de que o Busca Acelerada é atualizado em real-time, o que tornaria as páginas armazenadas em cache obsoletas rapidamente.

Se você tem memória sobrando no servidor ou possui páginas que são lentas para processar e quer melhorar seu desempenho, dê uma estudada sobre Output-Cache, que armazena as páginas HTML geradas pela sua aplicação na memória do servidor, evitando retrabalho.

Cache

Caso deseje armazenar dados na memória do servidor de uma forma mais gerenciável que na Session, aumentando o desempenho de sua aplicação, Cache é a solução. Não ensinarei aqui macetes de como usar cache, mas basta saber que é semelhante ao uso de Session mas é possível definir prazos de expiração para seu conteúdo baseados em tempo, em falta de uso por parte dos usuários ou até mesmo vincular a vida de um objeto em cache ao estado de uma arquivo ou pasta de arquivos.

Repeaters, ListViews, etc

Sempre pagine. Óbvio não?! Sempre que for trazer mais do que poucas dezenas de registros, pagine. E a paginação deve ser feita a nível de servidor, e não no lado do cliente. Um erro comum é os desenvolvedores quererem usar fantásticos paginadores escritos como plugins JQuery que puxam todos os dados do banco de uma vez só e depois apenas exibem de forma paginada, sendo que todos os dados tiveram de ser retornados e foram escritos no HTML. Isso é ruim do ponto de vista de performance e use apenas se for com poucos dados.

Outra dica ao usar estes controles é usar o mínimo possível de botões. Se você colocou um botão que leva o usuário para uma tela de edição com um ID como CommandArgument, porque não fazer simplesmente uma âncora (tag “a”) que leva para a tela de edição passando o ID como querystring? Muito mais leve e 100% funcional, evitando um postback desnecessário.

Evite o uso de DataBinder.Eval, pois ele usa Reflection para escrever os dados na tela. Ao invés disso, prefira fazer casting explícito sobre o Container.DataItem e chamar a propriedade que deseja.

Além disso, muito cuidado com os eventos ItemDataBound, que são executados uma vez para cada elemento que será apresentado na tela. Ele pode se tornar um imenso gargalo, principalmente se realizar consultas no banco de dados. O ItemDataBound é uma boa pedida se o seu controle de repetição possui muitas colunas, neste caso, pode ser mais eficiente montar uma string no ItemDataBound e escrever na tela com Response.Write, pois o eval do objeto será feito apenas uma vez dessa forma.

Redirecionamentos HTTP

Sempre que possível, use Server.Transfer para redirecionamentos dentro de uma mesma aplicação. Deixe o Response.Redirect somente para os casos de redirecionar para uma URL externa. E sob o ponto de vista de SEO, use o RedirectPermanent para avisar quando esse redirecionamento é para sempre.

Global.asax

Em aplicações que possuem tal arquivo, tome muito cuidado com o que você faz no mesmo, pois cada requisição feita à sua aplicação (o carregamento de uma imagem, um postback, um acesso pelo browser, etc) invocará este arquivo. Então se pretende colocar alguma lógica de aplicação neste arquivo, faça os testes corretos para garantir que você não efetuará sua lógica sobre requisições inofensivas, como imagens, JS e CSS, por exemplo. Libere tais requisições verificando a extensão de arquivo da requisição, quando houver.

Páginas Grandes e Complexas

Evite criar páginas ASPX muito grandes, especialmente com MultiViews cheias de Views ou páginas cheias de User Controls. Mesmo que a renderização do HTML seja dinâmica e alguns conteúdos não serão exibidos, o servidor dispenderá tempo processando esta página para gerar o HTML correto. prefira criar páginas separadas e menores para aumento de performance. Também evite uma hierarquia muito grande controles ou páginas, como múltiplas MasterPages ou User Controls dentro de User Controls.

Publicação

Aqui seguem algumas dicas de publicação do seu sistema em produção para que aumente a performance e reduza o consumo de memória:

  • compile como Release. Desta forma, suas DLLs ficarão menores, com até 15% de ganho em DLLs grandes. isso reduzirá o tempo de publicação (FTP) e o tempo de compilação da mesma no servidor, fora outros ganhos menores no próprio uso da aplicação.
  • compile para a plataforma de destino. Por padrão o ASP.NET mantém compatibilidade com servidores x32 e x64 sem nenhum ajuste. Entretanto, está cada vez mais comuns servidores com Windows Server 2008 R2, que por padrão, não existe em evrsão 32-bit. Dessa forma, porque manter uma compatibilidade que gera um overhead na compilação sem necessidade? Ajuste a arquitetura de compilação de seu projeto para x64 nas propriedades do mesmo, mas somente na configuração de Build para Release, para evitar problemas com sua máquina local. isso lhe trará ganhos de performance.

Manutenção

Mesmo que sua aplicação ASP.NET esteja pronta e publicada com sucesso, existem algumas dicas para melhorar a performance dela no servidor. Uma delas é reiniciar o seu application pool no IIS com certa frequencia, podendo inclusive deixar isso configurado no próprio pool. Reiniciar o pool limpa completamente a memória da aplicação, eliminando qualquer recurso indesejado que pode ter ficado pra trás e iniciando um novo processo em perfeitas condições de uso. Eu costumo fazer isso no máximo a cada 2 dias.

Conclusões

É muito provável que você faça essas alterações, mande rodar sua aplicação e…não veja diferença. Isso é normal. Cada uma dessas melhorias lhe dará milisegundos de ganho. A vantagem somente se dará quando atingir um volume de requisições, com vários usuários utilizando sua aplicação ao mesmo tempo, pois vários milisegundos virarão segundos, depois minutos e por aí vai. Um sistema ASP.NET bem construído pode ser tão veloz ou até mais do que a maioria das aplicações feitas com frameworks PHP, por exemplo, basta se estudar para isso.

Nos próximos posts sobre Tunning irei abordar otimizações de performance para sistemas escritos em C# e otimizações para modelagem e uso de bancos MS SQL Server. Ou seja, ao final desta série de posts (que começou com os posts sobre melhorias de performance em websites comuns) você terá em mãos muitas das técnicas que utilizo para que o Busca Acelerada consiga honrar o seu nome.

E você, conhece alguma melhoria de ASP.NET que já tenha utilizado e que não listei aqui?

Startups e Novidades

estas últimas semanas participei de dois eventos bem distintos, e igualmente interessantes, o Pitch Your Business e o SAP Startup Forum. Em ambos eu fui em busca de mais conhecimentos para aplicar em minha startup, o Busca Acelerada.

Pitch Your Business

Pitch Your Business

Este evento é organizado pela empresa junior da UFRGS, a PSJunior, que é uma empresa sem fins lucrativos mantida pelo trabalho social de alunos da Escola de Administração da federal gaúcha. A ideia do evento era que 10 empresas fizessem seu pitch no palco, recebendo feedback de um júri e ao final do evento, algumas delas receberiam consultoria gratuita da PSJunior, entre outros prêmios, para ajudar a alavancar sesu negócios.

Infelizmente fiquei sabendo de última hora e não pude inscrever o Busca Acelerada no evento, mas mesmo assim, não deixou de ser interessante. O que mais gostei neste evento é que destoou bastante dos eventos tradicionais que eu vou, recheado de startups de Internet. O PYB foi um evento de empreendedorismo, na sua mais pura essência. Tínhamos desde donos de Pet Shop, a mercadistas, passando por uma ideia de empresa de vigilância em escolas até as tradicionais startups de Internet. Tradicionais pelo menos no meu mundo, hehehehe

Duas delas me chamaram bastante a atenção e fazeram valer o evento na minha opinião: o Mercado Brasco e o Pizza Sessions. Não que as demais não tenham sido boas, como a Datamundus, que possui uma tecnologia para analisar e entender todo tipo de informação, o que é incrível. Mas é que estes empreendedores dessas duas empresas me chamaram a atenção pela paixão que possuem por seus negócios, embora não sejam as empresas mais incríveis do mundo e pelo fato dos negócios possuírem uma identidade próprio. O Brasco não é apenas um mercado, é um ponto de encontro do bairro Moinhos em Porto Alegre, e o Pizza Sessions não é apenas uma pizzaria, é uma escola para pizzaiolos amadores. Só vocês vendo as apresentações para vocês entenderem…

SAP - Best Big Data Solution

SAP Startup Forum

A gigante das indústrias de softwares empresariais, SAP, tem organizado pelo mundo todo eventos de fomento a startups que tenham interessem em utilizar o ecossistema SAP em suas plataformas. Em especial no momento eles tem divulgado muito sua nova plataforma de dados in-memory, o SAP Hana, e a primeira edição do SAP Hana Startup Forum no Brasil aconteceu ontem em São Leopoldo-RS. Como o Hana é um appliance para solucionar problemas de Big Data e Real-Time Analytics, ele cai como uma luva pro Busca Acelerada, que possui uma base imensa de anúncios. Pois bem, inscrevi a startup e fomos um dos 10 selecionados dentre 40 startups para se apresentar no palco do evento.

Além dos pitches de 4 minutos, o evento estava recheado de palestras e até uma mesa redonda sobre empreendedorismo com profissionais do Sebrae, Endeavor e Semente Negócios. Algo curioso é que apesar de ser um evento no Brasil, haviam palestrantes e convidados do mundo todo. Países como Alemanha, Índia, Argentina e Inglaterra marcaram presença no evento, logo, o idioma oficial do evento se tornou o Inglês. Salvo raras exceções, todo o conteúdo do evento foi em inglês e para quem não possuía domínio do idioma haviam tradutores simultâneos via rádio. Além dos pitches e das palestras o evento em si foi bem bacana, pois pude conhecer o SAP Labs Latin America e realmente é impressionante. Também pude conhecer uma galera show de bola, como a gurizada empresária da e-mine e o multi-talentoso Felipe Plets, que trabalha na própria SAP e é o cabeça do blog Pletax.

Voltando ao evento, apresentei o Busca Acelerada no palco principal e mais tarde, em meu próprio estande. Foi bacana, recebi muito feedback dos participantes do evento e não é que fomos premiados! O Busca Acelerada recebeu o prêmio de Best Big Data Solution e quem me entregou o prêmio em mãos foi ninguém menos que Kaustav Mitra, VP Global da SAP e Stefan Wagner, o presidente da SAP Latin America. Também tiramos vários fotos, mas ainda não estão disponíveis, atualizarei o post mais tarde com elas. Outros prêmios incluíam Most Innovative Solution, que foi dada a um empreendedor que propõe uma espécie de Google Reader 2.0 e People’s Choice que foi dado à empresa mais votada pelo público do evento.

Conclusões

Os eventos foram muito bacanas e são recomendadíssimos para suas próximas edições. E os próximos já estão marcados: no dia 22/04 estarei no curso Técnico em Informática da Escola Dom Feliciano, mas como palestrante sobre empreendedorismo digital, e no dia 24/04 estarei no Startup Meeting em Porto Alegre. Ainda não sei se conseguirei apresentar o Busca Acelerada por lá ou se apenas prestigiarei o evento. Obviamente farei um post a respeito, hehehehe.

Outras indicações para o pessoal que curte startups são a nova aceleradora de startups que surgiu em Porto Alegre, a WOW e o fantástico curso de Negócios Digitais promovidos pela Perestroika, também em Porto Alegre. Eu fiz um curso desses no ano passado com o pessoal da Semente Negócios e da Ionatec e foi fantástico!

Um abraço e até a próxima!

Otimizações de Desempenho em Aplicativos com Corona SDK

Artigo Traduzido do Blog Oficial

Boa tarde pessoal. Felizmente como as vendas do livro que traduzi sobre Corona SDK tem sido boas, e os leitores tem pedido novos posts no blog tratando de assuntos não vistos no livro, eis que volto a postar sobre o assunto. Como ando sem tempo para realizar experimentos com a plataforma por conta própria, decidi apenas traduzir este excelente post que foi publicado no blog oficial da Corona Labs, que pode ser acessado em http://www.coronalabs.com/blog/. Ou seja, não é de minha autoria, embora eu mesmo já tenha utilizado algumas dessas técnicas em meus projetos.

Otimizações de Performance

O tutorial de hoje é sobre otimização de performance, um tópico que preocupa todos desenvolvedores. Algumas dessas dicas serão óbvias – outras, nem tanto. Em todo caso, otimização de código tem de ser vista a partir de uma perspectiva de tempo vs. benefício. Se uma certa otimização pode render um ganho de 2% de performance em dispositivos antigos, mas sua implementação requer 50 horas de codificação adicional, então é ilógico fazê-lo. Entretanto, se 10 horas de codificação resultarão em um ganho perceptível entre vários grupos de dispositivos, então a tarefa é absolutamente valiosa.

A respeito de novos projetos, aderir a tantos truques de performance quanto possível é altamente recomendado, uma vez que eles resultam em aplicativos mais velozes e limpos, bem como uma melhor experiência para os usuários de diferentes dispositivos.

Rotinas de Tempo-Crítico

A maioria dos truques de performance apresentadps neste tutorial pertencem primeiramente a rotinas de “tempo-crítico” – ou seja, pontos na sua aplicação onde existe um monte de coisas acontecendo ou onde a experiência do usuário pode ser negativamente afetada por falhas de performance. Por exemplo, o gameplay de um jogo de ação, a espera entre carregar uma nova cena, etc. Se o usuário notar frame skips ou se ele tiver de esperar mais do que considera aceitável, isso refletirá na aplicação.

1. Localize, Localize

Não importa quantas vezes isso é mencionado, é muito valioso enfatizar novamente. Enquanto evitar variáveis e funções globais nem sempre é possível, o uso mínimo é a melhor prática. O acesso de variáveis locais e funções é simplesmente mais rápido especialmente em rotinas de tempo-crítico.

Não recomendado:

Recomendado:

Isto também se aplica às bibliotecas principais do Lua como a math. Em rotinas de tempo-crítico, você deve sempre localizar as funções da biblioteca.

Não Recomendado:

Recomendado:

E por último, lembre-se que funções sempre devem ser localizadas se possível. É claro, iso irá requerer escopo apropriado. Se você é um novato com Lua, leia este artigo.

Não Recomendado:

Recomendado:

2. Evite Funções como Argumentos para Outras Funções

Em laços ou código de tempo-crítico, é essencial localizar funções que serão parâmetros de outras funções. Examine estes dois casos:

Não Recomendado:

Recomendado:

3. Evite “table.insert()”

Vamos comparar quatro métodos de conseguir a mesma coisa: o ato comum de inserir valores em uma table. Dos quatro, a função Lua table.insert possui a performance mais sofrível e deve ser evitada.

Não Recomendado:

Recomendado:

Aceitável:

Recomendado:

4. Minimize o uso de “unpack()”

A função Lua unpack() não possui uma boa performance. Felizmente, geralmente é possível escrever um simples e mais rápido laço para fazer a mesma coisa.

Não Recomendado:

Recomendado:

O único porém é que você deve saber o comprimento da table para retornar todos seus valores neste tipo de método em loop. Entretanto, unpack() ainda tem seus usos – em uma table de comprimento desconhecido, por exemplo – mas deve ser evitada em rotinas de tempo-crítico.

5. Cache de Acesso a Itens da Table

Fazer cache de itens da table, especialmente dentro de laços, pode turbinar sua performance ligeiramente e pode ser considerada um código de tempo-crítico.

Aceitável:

Recomendado:

6. Evite “ipairs()”

Quando estiver iterando através de uma table, a sobrecarga da função Lua ipairs() não justifica seu uso, especialmente quando você pode conseguir a mesma coisa usando uma construção Lua.

Não Recomendado:

Recomendado:

7. Comparações de Desempenho Matemático

Várias funções e processos matemáticos são mais rápidos que outros e devem ser favorecidos.

Evite “math.fmod()” para Números Positivos:

Multiplicação é mais Veloz que Divisão:

Multiplicação é mais Veloz que Exponenciação:

8. Economize Memória de Texturas

Memória de texturas é muitas vezes ignorada até que chegue em um ponto crítico, quando é difícil fazer as alterações necessárias nas imagens do aplicativo.

A respeito de memória de texturas, imagens PNG de 8bit ou 24bit são todas empacotadas em imagens de 32bit. Elas são vetores retangulares de pixels e existem efetivamente 4 vetores de cores (canais) por imagem: vermelho, verde, azul e alfa (RBG+A).

Em OpenGL, texturas – independente se imagens simples ou folhas de imagens – também obedecem a regra da Potência de 2. Isto significa que qualquer textura arredondará para cima para a próxima potência de 2 (2,4,8,16,32,etc) referente à memória que irá ocupar. Desta forma, uma imagem dimensionada como 320×480 e outra dimensionada para 280×400 irão ambas consumir 512×512 de memória de textura. Note que a regra irá será aplicada na vertical ou horizontal, de forma independente e seu tamanho efetivo nem sempre é um quadrado – portanto, uma imagem dimensionada como 920×40 irá ocupar 1024×64 em memória, e não 1024×1024.

Enquanto isto pode parecer inócuo à primeira vista, vamos calcular o consumo real de memória. Não somente devemos considerar o tamanho com a regra da potência de 2, mas também os 4 canais de cores. Isto significa que cada pixel no vetor da textura requer 4 bytes de memória, e isto cresce mais rápido do que você imagina.

Imagem 350×500: 512x512px * 4 bytes = 1.048.576 bytes = 1MB

Imagem 512×1024: 1024x1024px * 4 bytes = 4.194.304 bytes = 4MB

Note que o arredondamente pela regra da potência de dois requer o quádruplo de memória para textura! Isto torna-se ainda mais preocupante quando você considera o desenvolvimento para dispositivos comuns e dispositivos Retina/HD. Se o tamanho das telas é o dobro uma da outra, como iPad vs iPad Retina, todas suas imagens precisarão do dobro de tamanho para não perderem qualidade. Entretanto, dobrando seu tamanho requer mais do que o dobro de memória de textura – 4x no exemplo acima – e genericamente falando, os dispositivos Retina/HD não possuem 4x mais memória que seus predecessores!

Antes que você entre em pânico, imagine que a memória de textura pode geralmente ser gerenciada sem uma quantidade excessiva de esforço ou (aham!) retrabalho em um grupo de imagens. Lembre-se apenas destas dicas:

1. Sempre descarregue texturas (remova-as da cena) quando não são mais necessárias.

2. Se você tem uma textura de background que precise ser 525×600 na tela, voc6e pode estar apto a criar uma imagem 448×512 para restringi-la ao intervalo 512 da regra da potência de dois. Então, no código, escale-a levemente definindo a largura e altura desejadas. Se for somente um pequeno aumento no tamanho, a minúscula perda de qualidade não será percebida pelos usuários, principalmente em dispositivos pequenos.

3. Reuse texturas se possível, e aplique cor com a API setFillColor(). Por exemplo, se você tem uma maçã vermelha e uma verde, voc6e pode criar uma maçã em escala de cinza e aplicar as cores vermelha e verde respectivamente.

4. Se você está usando folhas de imagens, considere usar uma ferramenta como Texturepacker para empacotar suas imagens na menor configuração da potência de dois possível.

9. Pré-crie Corpos Físicos

Se você pretende usar um número considerável de corpos físicos em seu cenário, pode ser sábio pré-criá-los em uma área de código que não seja de tempo crítico. Aqueles que não serão usados imediatamente podem ser definidos como inativos e colocados em algum lugar fora da tela ou em um grupo invisível, retornando ao estado ativo quando necessário.

Como tem sido dito, criar alguns corpos físicos durante um código de tempo-crítico não traz problemas – apenas evite criar entre 10 a 20 corpos físicos durante um ciclo do jogo, o que frequentemente refletirá em queda de frame rate.

Além disso, deve se usar esta técnica de maneira balanceada. Pré-criar e desativar 200 corpos físicos removerão eles do mundo do Box2D, mas não da memória do Corona, então não leve esta prática ao extremo.

10. Utilize as Melhores Práticas para Áudio

Efeitos sonoros para um aplicativo devem sempre ser pré-carregados em codigo não crítico, por exemplo, antes da cena ou fase começar. Adicionalmente, voc6e deve comprimir os sons para a qualidade aceitável com o menor tamanho na maioria dos casos. 11khz mono é considerada aceitável na maioria dos casos, como o usuário geralmente estará escutando através dos alto-falantes ou microfones do celular. Além disso, usando formatos simples multi-plataforma como WAV você economizará CPU.

Se desejado, efeitos sonoros podem ser organizados em uma table, para fácil referência e eventual descarregamento quando não forem mais necessários:

Com esta estrutura, playback é simples como:

Como sempre, não esqueça de limpar seus sons invocando dispose() neles quando não são mais necessários e limpando a referência da table:

Isto é tudo por hoje. Como um desenvolvedor, otimização de performance requer diligência, e você deve sempre aderir às melhores práticas. Espero que essas dicas forneçam conhecimento necessário para turbinar a performance de seus aplicativos. Como sempre, contribua com seus questionamentos e comentários abaixo.

* OBS: curtiu o post? Então dá uma olhada no meu livro de Corona SDK clicando no banner abaixo pra aprender a criar outros tantos apps incríveis!

Livro Corona SDK
Livro Corona SDK