R√°pido como a Morte 

Sep/09
11

Hoje em dia √© comum ouvir dizer que a velocidade com que a aplica√ß√£o executa as suas atividades ‚Äď chamada empiricamente performance – ¬†n√£o deve ser uma preocupa√ß√£o¬†para a vers√£o 1.0 de um software. Existe at√© um ditado ‚ÄúPrimeiro faz funcionar, depois faz funcionar bem e depois faz funcionar depressa‚ÄĚ.

Em pleno s√©culo XXI quando as pr√°ticas de teste preventivo se t√™m mostrado mais eficazes, n√£o faz sentido que o ‚Äúfuncionar bem‚ÄĚ seja um preocupa√ß√£o secund√°ria e o mesmo pode ser defendido para a performance.

Acho que ninguém terá tido a experiência de ver um utilizador pedir para ter um software mais lento. Todos querem o mais rápido que o seu dinheiro pode comprar.

Isto significa que performance n√£o √© algo que se ajusta depois. √Č um requisitos can√īnico, sempre presente, que deve ser pensado em todos os momentos e pontos da aplica√ß√£o ao lado da seguran√ßa, por exemplo.

Em paralelo, est√° se generalizando a ideia de que porque o desenvolvimento de software √© um processo iterativo as primeira itera√ß√Ķes podem ser completamente feitas √† toa sem ter que pensar ou decidir √† priori coisas relevantes como a arquitetura ou o design.

Isto nada mais é que uma pequena confusão entre processo iterativo e processo evolutivo.

A construção do software é feita à conta de processos iterativos. Só depois dele estar construído é que  pode evoluir. O processo ser iterativo significa que defeitos imprevistos são ser corrigidos e requisitos imprevistos são ser equacionados à media que vão aparecendo, não singifica que ser parte de um monte de código , design e arquitetura meia-boca e se vai corrigindo todo um conjunto de problemas que foram incluídos no inicio.

N√£o considerar a performance um requisito can√īnico e pensar que tudo pode ser solucionado depois¬† levam ao descaso pela preocupa√ß√£o em prevenir problemas de performance ou prevenir refactoring desnecess√°rio. N√£o √© porque voc√™ pode emendar algo, que voc√™ vai come√ßar por sempre fazer errado.

√Č dif√≠cil definir o que ‚Äúperformance‚ÄĚ significa, por significar simultaneamente v√°rias coisas, mas normalmente sempre est√° associada √† aus√™ncia de momentos de espera. V√°rios fatores externos podem afetar a performance ,causando necessidade de espera, tais como o uso da banda em uma conex√£o remota. Mas muitos dos fatores que influenciam a performance s√£o internos.

Poderíamos dividir os fatores internos que influenciam a performance em três categorias: arquiteturais, de design e de codificação. Os fatores arquiteturais são normalmente chamados fatores de escalabilidade porque a este nível a velocidade só pode ser aumentada utilizando mais máquinas ou adicionar mais recursos na mesma máquina. Contudo, isso só pode ser feito se a aplicação está preparada para ser distribuída por várias máquinas. Este tipo de estrutura tem que ser avaliada e decidida antes de começar a codificar o software, pois esta distribuição se refletirá diretamente nas responsabilidades de cada nodo que, por sua vez, refletiram nas responsabilidades das classes e código escrito para cada nodo.   Mudar a arquitetura tem um impacto profundo no sistema que pode ter um custo ou esforço proibitivo.

Fatores de design s√£o tamb√©m importantes. Se a aplica√ß√£o trabalha com certo tipo de dom√≠nios ou tem certos tipos de necessidade (processamento em massa, por exemplo) ent√£o isso tem que ser equacionado na atribui√ß√£o de responsabilidades de cada classe durante o design. Alterar responsabilidades de design √© mais f√°cil que mudar as de arquitetura mas pode incluir v√°rias rachaduras na arquitetura vigente. Por isso √© bom que ambas as coisas sejam equacionadas juntas para resolverem todos os problemas j√° previstos antes de come√ßar a codificar. √Č isto que se chama ‚Äúsolu√ß√£o por design‚ÄĚ; o problema n√£o vai aparecer porque o sistema foi desenhado para que ele nunca existisse.

Fatores de codificação são os mais difíceis de encontrar. Muitas vezes correspondem ao uso incorreto de algoritmos, ao uso de objetos caseiros em vez da API padrão, mas principalmente advém da realidade que o código é maior que a soma das suas partes e portanto difícil de reconhecer à partida onde estarão os problemas.

Fatores de código realmente escapam pelos dedos devido ao uso de API de terceiros e outros tipos de código que não dominamos. Entenda-se que estes fatores estão ocultos à primeira vista e por isso eles afetam a performance. Se tivessem sido identificados antes, não mais estariam lá para atrapalhar pois teriam sido eliminados por um design mais cuidadoso.

√Č preciso deixar bem claro que decis√Ķes como utilizar um mapa em vez de uma itera√ß√£o sobre uma lista de objetos s√£o decis√Ķes de design e v√°lidas √† partida. N√£o constituem um refinamento de performance. Constituem, isso sim, a op√ß√£o correta para resolver o problema. A utiliza√ß√£o do padr√£o Produtor-Consumidor √© mandat√≥ria nos cen√°rios onde foi identificado que o uso do padr√£o aumenta a performance. E tanto que √© assim, que existe um mundo completo de API e produtos relacionado a este padr√£o. A API padr√£o √© a Java Messaging Service (JMS) que, embora o nome sugira que se trata de uma tecnologia para envio de mensagens, nada mais √© que a especifica√ß√£o robusta do padr√£o Produtor-Consumidor.

Mesmo aplicando todas as solu√ß√Ķes conhecidas pelo estado-da-arte sempre √© poss√≠vel que alguma falha na integra√ß√£o de API ou nas decis√Ķes de design e arquitetura cause alguma entropia que acaba se manifestando em baixa performance. Para resolver estes ¬†fatores de c√≥digo n√£o resta muito mais que utilizar uma ferramenta de profiling e verificar onde est√£o os problemas.

Só que ferramentas de profilling apenas de lhe dirão quais métodos de quais classes estão demorando mais e quais objetos estão sendo construídos e destruídos mais, e quais estão ocupando a memória por mais tempo. Ferramentas de profiling não lhe dirão que o seu design é falho ou a sua arquitetura sustentada com palitos. A analise para um bom design e arquitetura é abstrata e mental, nenhum ferramenta poderá fazer isso por você.

O exemplo cl√°ssico de como n√£o proceder √© o cl√°ssico caso processamento em massa (em batch). Quem nunca escreveu um na m√£o que d√™ um passo em frente…

A ideia √© processar um conjunto de dados o mais absurdamente volumoso poss√≠vel no tempo mais curto poss√≠vel. Sabemos que um simples for n√£o vai dar conta e j√° pensamos em paralelizar o processamento. Isso √© o que √© esperado de qualquer estudante do segundo ano. Mas como implementar isso? Se n√£o tivermos cuidado procurando a arquitetura e design corretos para este problema, acabaremos tendo um c√≥digo caseiro de processamento em batch que ‚Äď como todos sabem ‚Äď nunca √© r√°pido de primeira.

A primeira coisa que temos que fazer n√£o √© sair codificando e esperar que v√°rias itera√ß√Ķes resolvam o problema… A verdadeira solu√ß√£o adv√©m de procurar se j√° foi identificada uma forma padronizada de resolver o problemas.

Estamos com sorte. Essa forma já foi identificada e se chama Padrão Produtor-Consumidor.  Mas um padrão tem muitas formas de ser implementado. Vamos começar implementando a nossa forma? Não. Calma.

Primeiro vamos desenhar os intervenientes neste processo de forma abstrata (usando defini√ß√£o de interfaces, contratos e atribuindo responsabilidades) conforme o padr√£o especifica. Ap√≥s isso pensamos em implementa√ß√£o. Como o nosso design √© flex√≠vel v√°rias implementa√ß√Ķes s√£o poss√≠veis. A primeira a tentar e mais interessante √© aquela que j√° exista. Mais uma vez estamos com sorte. A JMS serve que nem uma luva.

Agora basta colar a JMS com as nossas interfaces (padr√£o Bridge) e voil√°, temos um modulo de processamento em batch sem quase escrever nenhum c√≥digo e logo na primeira itera√ß√£o. Mas se n√£o gostarmos de JMS ou n√£o o podermos utilizar por alguma raz√£o, podemos olhar outras op√ß√Ķes como o Spring Batch, por exemplo. ¬†O ponto √© que se escolher bem o seu design e arquitetura poder√° facilmente usar o que j√° existe e at√© trocar depois para outra solu√ß√£o se a primeira n√£o foi satisfat√≥ria. Essa flexibilidade n√£o s√≥ o ajuda a saber mais sobre o problema mais o ajuda a se esfor√ßar menos.

Otimiza√ß√£o prematura de performance de fatores de c√≥digo √© imposs√≠vel. Ela requer que o sistema esteja ponto e que seja poss√≠vel execut√°-lo em v√°rios cen√°rios de forma a analisar o que acontece na mem√≥ria e no processamento da JVM. Contudo a escolha certa de padr√Ķes de design e arquitetura n√£o √© evolutiva e deve ser feita √† priori, porque escolher o design ou arquiteturas erradas levar√£o a pesados esfor√ßos e custos de remodela√ß√£o do sistema como um todo. Especialmente, ela deve ser baseada em padr√Ķes que j√° tenham implementa√ß√Ķes e que j√° se provaram competentes. Para isso √© vital que sejam conhecidas com anteced√™ncia as necessidades e expectativas de performance do cliente.

Conhe√ßa as expectativas do cliente quando a performance. N√£o aceite ‚Äúisso n√£o √© importante agora‚ÄĚ. Desenhe para performance (e seguran√ßa e qualquer outro requisito n√£o-funcional) com a mesma astucia que desenha para requisitos de neg√≥cio. Desenha a aplica√ß√£o para ter f√°cil manuten√ß√£o e n√£o para que funcione.

Se a aplicação tem fácil manutenção e não funciona é trivial corrigi-la. Se ela funciona, mas é difícil de manter, é inerente uma falha inesperada a qualquer momento.

Otimizar significa ‚Äútornar √≥timo‚ÄĚ. Tornar √≥timo √© realmente um detalhe, mas tornar f√°cil agora tornar √≥timo depois √© o desafio. Vai encarar? Ou vai continuar pensando que itera√ß√Ķes s√£o evolu√ß√Ķes?

Um comentário para “R√°pido como a Morte”

  1. Boa Tarde,

    Sergioooo !!!

    Quero dizer que foi um excelente texto, mas gostaria de compartilhar alguma de umas duvidas.

    A performance ela √© reflexida ao contexto de tecnologias que v√£o abra√ßar determinado cen√°rio, falando em J2EE/JEE o que seria uma vis√£o para a Oracle na otica de seus produtos, a mesma √© dominante e lider Mundial como vendor.O que ao meu ver atinge o mundo corporativo √© a escolha de fazer algo barato mas com inteligencia ao ROI e sobre os recursos Open Source ou de licen√ßa planejada que fa√ßam elas terem econominas futuras √† se encaixarem como partners de grandes players,e que possam se tornarem produtivos e desfrutar de uma infra-tecnologica aceit√°vel, porque usar JBoss se Websphere √© mais scal√°vel e est√°vel ou derrepente pra usar Webshpere se posso usar Bea Weblogic OSB para gerenciar melhor quest√Ķes de SOA para ESB, e assim vai.

    Abra√ßossss….

Comente

Enquete

Sobre quais assuntos gosta de ler neste blog ?

View Results

Loading ... Loading ...

Artigos