You are on page 1of 6

Arquitetura de Software

Arquitetura: Princpios para alcanar Desempenho e


Escalabilidade em Aplicaes
Otavio Pecego Coelho
Arquiteto de Solues
DPE - Microsoft Brasil
Novembro - 2004

Introduo
Trabalhando na Consultoria da Microsoft Brasil tive por vrias vezes a oportunidade de lidar com
problemas de performance e escalabilidade em aplicaes. Muitas vezes conseguimos avanos
espantosos com pequenas modificaes no cdigo ou estrutura dos mdulos dos programas.
Hoje, como Arquiteto de Solues da Microsoft, sou muitas vezes chamado para explicar de forma
concisa como conseguir boa performance e escabilidade com a tecnologia .Net. Neste exerccio,
me dei conta que com alguns poucos princpios gerais conseguimos explicar muitas das boas
prticas de desenho e arquitetura que levam a bons resultados.
Este artigo apresenta estes princpios que considero como os mais bsicos e enumera algumas das
suas conseqncias tanto para o design quanto para a implementao de aplicaes.
Incio da pgina

Princpios
So seis os princpios bsicos que encontrei e que podem ajudar na deciso relativa escolha de
uma tecnologia ou padro de design.
Um ponto importante, que logo vocs iro notar, que alguns princpios so conflitantes. Isto
acontece porque estamos tentando alcanar dois objetivos ao mesmo tempo: desempenho e
escalabilidade.
O desempenho est relacionado ao quo rpido uma tarefa computacional pode ser executada.
Idealmente, o desempenho no trata da questo do limite fsico de uma mquina (seja CPU,
memria, disco, etc). Algoritmos podem ser classificados de acordo com a sua estrutura interna.
De acordo com este ponto de vista, minimizar o nmero de passos de uma computao o
objetivo prioritrio.
A escalabilidade, por sua vez, incorpora os limites fsicos questo do desempenho. Como se
comporta o desempenho quando atingimos os limites fsicos das mquinas, e que estratgias
devemos utilizar para aumentar a quantidade de processamento disponvel.
Duas so as linhas mestras para atingir maior escalabilidade: o incremento com novos hardwares
ou a substituio por novos hardwares de maior desempenho.
O primeiro denominado escalabilidade horizontal. O exemplo tpico um farm Web, onde
podemos incorporar novas mquinas ao farm para dar conta do aumento da demanda pelos
usurios finais.
O segundo a escalabilidade vertical, onde uma nova mquina mais possante substitui a antiga.
Na relao entre custo e benefcio, mais comum que a escalabilidade horizontal ganhe, no
s devido aos custos reais ($$), mas tambm devido aos benefcios de segunda ordem, como a
melhoria da disponibilidade.
Juntar estas duas perspectivas (desempenho e escalabilidade) parte da arte de um arquiteto.
Neste exerccio de equilbrio, surgiram as arquiteturas cliente-servidor, 3-camadas, n-camadas,
uso de caching, monitores transacionais, etc.
Interessante notar que todas estas arquiteturas foram estruturadas de acordo com alguns
princpios bsicos. Dentre eles, os que entendo serem mais relevantes so:

Aproximar Algoritmos aos Dados

Aumentar o Paralelismo
No Estabelecer Afinidade
Minimizar Contenes
Minimizar o Uso de Recursos
Pr-alocar e Compartilhar Recursos Caros

Abaixo descrevo o que so e a motivao de cada um destes.


Princpio 1: Aproximar Algoritmos aos Dados
Dados e algoritmos (que operam sobre estes dados) devem estar o mais prximo possvel. Se
estiverem distantes, o tempo de acesso aos dados se deteriora, causando um desempenho pior. O
lugar mais prximo entre os dois ocorre dentro da mesma mquina e do mesmo processo. Se o
dado estiver em disco, j existe retardo - que considervel em relao memria local. Se
estiver em outra mquina interligada via rede, o retardo poder ser comparativamente imenso.
Este princpio j utilizado h muito pelos arquitetos de hardware. CPUs costumam ter
registradores e estes tm velocidade de acesso muito maior do que a do acesso memria RAM.
Parte do trabalho dos otimizadores dos compiladores modernos o de alocar corretamente as
varveis de um programa nos registradores da CPU.
Velocidade e latncia so os dois atributos principais. Quanto mais veloz o meio para o acesso e
quanto menor a latncia, melhor. A velocidade pode ser a da luz, mas se a latncia devido a
distncia for muito grande, no temos desempenho.
Podemos imaginar uma rede de alta velocidade, mas se o protocolo entre camadas for
inadequado, parte do benefcio roubado.
Princpio 2: Aumentar o Paralelismo
Aumentar o paralelismo nem sempre factvel - mas costuma ser factvel na maioria das vezes. O
princpio simples: quanto mais hardware voc conseguir manter trabalhando ao mesmo tempo,
maior performance voc vai ter.
Hoje, nossos computadores de casa e do escritrio j so multi-CPUs e fazem isto para aumentar
a performance. Unidades de processamento aritmtico, placas grficas, controladoras de discos
rgidos, hyper-threading, etc. Os engenheiros esto sempre encontrando maneiras de paralelizar
processamento para ganhar desempenho.
Nesta perspectiva, a grande dificuldade para a programao evitar que o algoritmo se torne
muito complexo.
O interessante que a pesquisa sobre Processamento Transacional nas ltimas 3 dcadas facilitou
enormemente a implementao do paralelismo entre tarefas. Bancos de Dados O grande
exemplo aqui. Hoje programamos nossas tarefas de negcio assumindo naturalmente que muitas
instncias destas tarefas estaro sendo executadas ao mesmo tempo porque deixamos o controle
da concorrncia para o Banco de Dados. Ao utilizar esta tcnica, aumentamos potencialmente o
poder de escalabilidade horizontal, j que novas mquinas podero estar sendo incorporadas para
realizar mais tarefas em paralelo e, portanto, aumentando no tempo o nmero total de tarefas
que podem ser realizadas.
Este o caso timo - no o realista. Afinidade e Conteno so dois pontos que atrapalham o grau
de paralelismo que podemos alcanar. Mas isto tema para os dois prximos princpios.
Princpio 3: No Estabelecer Afinidade
Afinidade o nome a que se d quando certa tarefa fica amarrada a um lugar fsico. Por exemplo,
se apenas uma mquina possuir um recurso (por exemplo, o Banco de Dados), todos seus
usurios estaro amarrados esta mquina. Isto causa problemas de conteno no acesso ao
recurso (todos competem pela rede, CPU, memria e disco do Banco de Dados), quando

poderamos pensar no uso de um pool de recursos (conjunto de Bancos de Dados replicados em


mquinas diferentes) para diminuir esta conteno e aumentar o paralelismo.
Este exemplo do Banco de Dados em vrias mquinas no usual, devido dificuldade de
implement-lo. Quando implementado, a tcnica normalmente usada a da fragmentao de
tabelas ou replicao. Estaremos vendo o porqu disto mais adiante. O uso de cache local nos
clientes do Banco outra tcnica possvel.
Note que podemos aumentar o paralelismo e ainda manter a afinidade. Por exemplo, podemos
imaginar o aumento de mquinas para processamento de regras de negcio, mas mantendo a
afinidade ao servidor de Banco de Dados. Se o limite do Banco no for atingido rapidamente, esta
estratgia de paralelismo pode ser muito eficaz (sendo, creio eu, a tcnica mais utilizada hoje em
dia).
Outra tcnica usual de paralelismo o pipeline, onde cada mquina ou tarefa executa uma parte
do processamento. A afinidade total, mas a performance pode ser excelente dependendo da
estrutura do problema/soluo.
Princpio 4: Minimizar Contenes
Conteno significa aguardar numa fila para poder ser servido. Existem vrias filas na execuo de
tarefas em uma arquitetura moderna. Filas de disco, filas de espera da liberao do locking de
certos registros ou tabelas do Banco de Dados, etc.
Contenes so difceis de serem tratadas e podem causar deadlocks. Embora muitas ferramentas
implementem schedulers que reordenam seqncias de operaes conflitantes (que o que
acontece num Banco de Dados), muitas vezes temos que ajudar com esta ordenao tambm em
nossos algoritmos - como veremos mais adiante.
Princpio 5: Minimizar o Uso de Recursos
Recursos sero sempre escassos a partir de certo nmero de usurios e tarefas concorrentes seja cpu, memria, disco, rede, etc.
Normalmente no nos damos conta de que estamos usando recursos demais nos nossos
algoritmos. Por exemplo, costumamos passar mais parmetros do que deveramos em nossas
chamadas a mtodos e procedimentos - tudo em nome da generalidade. Outro exemplo o total
descuido que temos quanto ao tempo em que alocamos um recurso.
J perdi a conta do nmero de vezes que observei locks de linhas de tabelas de banco de dados
serem feitas muito antes do uso real dos valores lidos - aumentando o tempo de conteno de
outras tarefas. comum tambm ver abuso no armazenamento de dados em variveis de sesso
(uso de memria) ou no envio de conjuntos de dados imensos entre camadas da aplicao.
Um ltimo exemplo e muito comum o abuso no volume de dados retornado por uma query de
banco de dados. Quando fazemos isto estamos gastando tempo, rede e memria.
Todos estes so exemplos da nossa tendncia natural a gastar mais do que precisamos - o que
far falta em condies de stress.
Princpio 6: Pr-alocar e Compartilhar Recursos Caros
Recursos caros devem ser pr-alocados e compartilhados. Recursos podem ter um tempo muito
longo de construo (inicializao), como conexes de banco de dados ou rede. T-los construdos
antes da hora do uso parte do truque para obter melhor desempenho.
Porm, nem sempre estes recursos estaro em uso. Por que no deix-lo descansando para a
prxima vez? Este um dos princpios do uso da tcnica de Cache ou pool de recursos (pool de
objetos, conexes, etc).
Princpio 7: Manter a Corretude e Simplicidade
Sim, este princpio no estava listado. Nem seria preciso caso no tivssemos a mania de, por
vezes, procurar mais paralelismo e desempenho esquecendo-nos da corretude e simplicidade.
Nossos sistemas devem ser corretos - ponto!

A simplicidade nos ajuda a mant-los corretos e com um custo aceitvel. Realizamos isto via
abstraes - como tarefas, monitores de transao, etc.
Princpio 8: Use um Algoritmo e Estruturas de Dados Eficientes
Este tambm no estava listado... bvio, mas infelizmente ainda existe pouco conhecimento das
tcnicas de anlise da complexidade de algoritmos entre os desenvolvedores que tenho conhecido.
freqente o uso de estruturas de dados e algoritmos ineficientes. Existem boas referncias sobre
este assunto, embora recheadas de matemtica pesada...
Incio da pgina

Tcnicas para Performance e Escalabilidade


Os princpios aqui listados implicam em conseqncias de design. Como exerccio, comento abaixo
algumas prticas atuais que so decorrentes do uso destes princpios.
Tcnica 1: Minimize Interaes entre Fronteiras
Fronteiras so caras (Princpio 1) mas podem escalar horizontalmente pois, muitas vezes,
permitem a possibilidade do aumento do paralelismo em processos ou CPUs diferentes (Princpio
2).
Este um caso tpico de conflito entre princpios, mas onde aceitamos pagar o preo de ter
fronteiras (o que significa retardos) para ganhar paralelismo.
Como queremos o benefcio de processos em separado, e como sabemos que existe um custo
associado, a soluo minimizar as interaes, seja minimizado o nmero de chamadas, e/ou
minimizando o volume de dados passados.
O bom uso da primeira tcnica quando em uma nica chamada passamos todos os parmetros
necessrios para que a outra parte faa o seu trabalho e quando esta devolve apenas os dados
necessrios do resultado. Nada de muitas idas e voltas de parmetros e resultados devido a
chamadas intensas de mtodos e acesso a propriedades.
Um exemplo de dados necessrios est no retorno consciencioso das colunas realmente utilizadas
pelos clientes, no caso de uma query ao banco de dados.
Outro exemplo de conflito entre princpios est no retorno de um grande result set. Embora isto
minimize idas e vindas, esta tcnica vai contra o princpio 5, pois causa excesso de uso de
memria e rede. Melhor usar a tcnica de paginao j no acesso ao banco de dados.
Tcnica 2: Evite Referncias para objetos Remotos
Aqui estamos no famoso caso do stateless contra stateful. Referncias a objetos remotos so o
caso do stateful e implicam em afinidade (o que vai contra o Princpio 3). Alm disso, como os
objetos remotos ficam presos na memria esperando sua liberao pelo cliente, o uso de
referncias vai contra o Princpio 5.
Tcnica 3: Obtenha o mais tarde e Libere o Mais Cedo
Esta uma recomendao bem entendida, mas muito pouco obedecida pelos desenvolvedores.
So os Princpios 4 e 5 que pedem que esta regra seja obedecida, mas na maior parte dos casos,
o designer das classes ou do algoritmo no leva em conta a performance. comum fazer um
modelo de classes, determinar seus mtodos, e perder o contexto do uso dos recursos que so
utilizados por estes mtodos. Logo estamos fazendo o diagrama de interao e no sabemos mais
quando comearam as operaes que fazem lock no banco de dados ou que simplesmente alocam
conexes de um pool. Em conseqncia, aumentamos o tempo de conteno desnecessariamente,
deteriorando o desempenho do sistema em momentos de stress.
Um esboo para um padro de codificao que garanta uma performance melhor :
1.

Coletar todos os dados possveis que no precisem do Banco de Dados (parmetros, cache,

2.
3.

etc);
Conectar com o Banco;
Coletar todos os dados (com o mnimo de interaes) que no impliquem em lock, necessrios
para realizar a ao;

4. Realizar contas e procedimentos possveis de serem feitas s com estes dados;


5. Ir ao banco de dados (com o mnimo de interaes) para realizar operaes que exigem lock;
6. Liberar a conexo;
Tcnica 4: Minimize o uso de Stored Procedures
O Princpio 1 diria: "use apenas stored procedures". No entanto, esta deciso pode causar grandes
problemas para o Princpio 2 devido escalabilidade.
Stored Procedures tm vrias vantagens. Primeiro, so pr-compiladas - o que significa menos
processamento. Segundo, no h nada mais perto de um dado no Banco de Dados.
No entanto, Banco de Dados so Monitores de Transao muito especializados em quatro funes:
Sort, Merge, gerncia de Locks e Log para recuperao em caso de acidentes.
De todos estes, a gerncia de Lock uma das tarefas mais crticas para a implementao de
algoritmos distribudos. Este o real motivo de existirem poucos Bancos de Dados que possam
implementar a escabilidade horizontal. A gerncia de Locks pede memria compartilhada (Princpio
1) o que impede arquiteturas distribudas ( menos que o problema de intercomunicao seja
minimizada - o que esto tentando fazer com HPC - High Performance Computing).
O que isto tem a ver com stored procedures? Bem, se as mquinas de Banco de Dados tm
dificuldade de escalar horizontalmente, ela um recurso escasso e precioso. Temos ento que
otimizar seu uso para que ela faa apenas o que sabe fazer bem.
Da o conselho freqente de deixar de fora do banco toda a manipulao de strings, clculos e
decises de negcio e implementar em stored procedures os comandos mais bsicos. Como esto
em stored procedures, no so recompiladas. Como fazem apenas o que os Bancos melhor sabem
fazer, utilizamos melhor o recurso e adiamos, ao final, a necessidade de escalar verticalmente.
Tcnica 5: Utilize Pool de objetos e Cache
Os Princpios 1, 5 e 6 nos levam ao uso de Pool e Cache.
Muitos dados so lidos com muita freqncia e so raramente modificados (um exemplo o uso
de tabelas de metadados e de certos cadastros bsicos). Gastar tempo, banda e Cpu do Banco de
Dados para traz-los fere os Princpios 1 e 5. Melhor traz-los no incio (Princpio 6) e garantir que
esto locais (Princpio 1).
No entanto, dois cuidados devem ser levados em conta:
1.
2.

No use espao demasiado da memria - contradizendo o Princpio 5 para o item memria.


Se houver escrita e precisarmos de propriedades ACID, estaremos incorrendo no problema de
sincronizao e lock entre vrios caches - j que um cache naturalmente introduz afinidade
(ver Princpio 3). Se a poltica de renovar o cache de tempos em tempos no for suficiente, o

melhor, neste caso, usar o Banco de Dados.


Objetos que custam caro para inicializar merecem uma tcnica semelhante: o pool. Nele, varos
objetos so pr-inicializados e fica espera de chamadas. Uma vez chamados, ficam alocados
tarefa corrente at que, uma vez liberados, retornem ao pool.
Tcnica 6: Use, quando possvel, Tcnicas Assncronas
Filas podem ser criadas por bons motivos: seja para manter a consistncia de dados (ex.: filas de
conteno devido locks), ou para diminuir o risco do uso indiscriminado de recursos.
O uso de tcnicas assncronas, quando permitido pelas regras de negcio, traz algumas
oportunidades de otimizao no uso de recursos. Com o enfileiramento de mensagens em
sistemas de filas (como o MSMQ), podemos alocar recursos limitados e suficientes para o
tratamento das mensagens. Com isto, poderemos consumir aos poucos os elementos da fila sem
aumentar os recursos em momentos de pico. Exemplo: disponibilizamos 10 threads para
tratamento de um tipo de requisio e no estaremos usando mais recursos caso haja um pico de
requisies. O tempo mdio do tratamento ser maior (devido ao tempo de espera), mas
estaremos garantindo um limite no uso dos recursos (Princpio 5)
Incio da pgina

Concluso
Muitas outras tcnicas de performance podem ter seu impacto medido de acordo com os princpios
apresentados. O texto Improving .NET Application Performance and Scalability
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenet.asp)
uma referncia bem completa sobre este assunto. Meu conselho t-los em mente em toda
deciso de design a ser feita em um projeto. O balanceamento destes princpios pode significar o
sucesso ou fracasso da sua aplicao.
Lembre-se tambm que voc no precisa de performance em todos os momentos. Como a
exigncia de performance pode levar tcnicas de razovel complexidade, voc poder estar
onerando em demasia o seu projeto. Por isto, estabelea na fase de requerimentos os pontos
crticos de performance a serem obtidos. Com isto, voc poder priorizar questes como reuso e
manutenabilidade e utilizar tcnicas de performance em situaes realmente necessrias.
Incio da pgina
Verso para Impresso

Enviar esta Pgina

Adicionar a Favoritos

Fale Conosco |Imprima esta pgina |Adicione aos Favoritos


2005 Microsoft Corporation. Todos os direitos reservados. Nota Legal |Marcas
comerciais |Poltica de Privacidade

You might also like