Entendendo a Performance em Aplicações Java - FLF
Entendendo a Performance em Aplicações Java - FLF
Entendendo a Performance em Aplicações Java - FLF
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
FACULDADE LOURENÇO FILHO<br />
Curso de Ciência da Computação<br />
José Tiago Ribeiro Filho<br />
ENTENDENDO A PERFORMANCE<br />
EM APLICAÇÕES JAVA<br />
Fortaleza – Ceará<br />
Dez<strong>em</strong>bro de 2010
FACULDADE LOURENÇO FILHO<br />
Curso de Ciência da Computação<br />
José Tiago Ribeiro Filho<br />
ENTENDENDO A PERFORMANCE<br />
EM APLICAÇÕES JAVA<br />
Monografia apresentada ao Curso de Ciência da<br />
Computação da Faculdade Lourenço Filho, como<br />
requisito parcial para obtenção do grau de<br />
Bacharel <strong>em</strong> Ciência da Computação.<br />
Orientador: Prof. MSc. João Frederico Roldan<br />
Viana.<br />
Fortaleza – Ceará<br />
Dez<strong>em</strong>bro de 2010
FACULDADE LOURENÇO FILHO<br />
Curso de Ciência da Computação<br />
Título do Trabalho: <strong>Entendendo</strong> a performance <strong>em</strong> aplicações java<br />
Autor: José Tiago Ribeiro Filho<br />
Banca Examinadora<br />
_________________________________<br />
João Frederico Roldan Viana, MSc. (<strong>FLF</strong>)<br />
Orientador<br />
_________________________________<br />
André Barros Pereira, MSc. (<strong>FLF</strong>)<br />
1º M<strong>em</strong>bro<br />
_________________________________<br />
Francisco Nauber Góis, MSc. (<strong>FLF</strong>)<br />
2º M<strong>em</strong>bro<br />
Aprovado <strong>em</strong> 21 de Dez<strong>em</strong>bro de 2010.
“É melhor tentar e falhar, que<br />
preocupar-se e ver a vida passar.<br />
É melhor tentar, ainda que <strong>em</strong> vão que<br />
sentar-se, fazendo nada até o final.<br />
Eu prefiro na chuva caminhar, que <strong>em</strong><br />
dias frios <strong>em</strong> casa me esconder.<br />
Prefiro ser feliz <strong>em</strong>bora louco, que <strong>em</strong><br />
conformidade viver”.<br />
Martin Luther King.
sabedoria.<br />
mim dada.<br />
orientação.<br />
AGRADECIMENTOS<br />
Agradeço <strong>em</strong> primeiro lugar a Deus, orig<strong>em</strong> da vida e fonte de<br />
A meus pais pelo estímulo <strong>em</strong> todos os momentos, e educação a<br />
A meus irmãos que s<strong>em</strong>pre que precisei estiveram ao meu lado.<br />
Ao professor Frederico Viana, pelo incentivo constante e pela segura<br />
E a todos aqueles que, direta ou indiretamente, contribuíram para a<br />
elaboração desta monografia.<br />
Muito Obrigado.
RESUMO<br />
A monografia traz a definição de performance computacional, focando<br />
des<strong>em</strong>penho <strong>em</strong> aplicações desenvolvidas <strong>em</strong> <strong>Java</strong>, explica aspectos<br />
importantes que influenciam no des<strong>em</strong>penho tais como: utilização da m<strong>em</strong>ória<br />
RAM, t<strong>em</strong>po de inicialização, escalabilidade e a performance percebida pelo<br />
usuário do sist<strong>em</strong>a. Apresenta uma técnica muito importante para medição de<br />
des<strong>em</strong>penho, chamada benchmark de des<strong>em</strong>penho, explica o quanto o seu<br />
uso pode auxiliar o desenvolvedor a ter um acompanhamento de possíveis<br />
mudanças de des<strong>em</strong>penho no processo evolutivo da aplicação. Fornece uma<br />
visão sobre algoritmos e estruturas de dados, como sua escolha pode<br />
influenciar muito na velocidade de um software, define garbage collection, sua<br />
importância para bom funcionamento da aplicação e traz uma visão sobre<br />
arquitetura da maquina virtual HotSpot.
ABSTRACT<br />
The monograph has a definition of computational performance, focusing on<br />
performance in applications developed in <strong>Java</strong>, explains important aspects<br />
influencing the performance such as: use of RAM, startup time, scalability and<br />
performance as perceived by the user of the syst<strong>em</strong>. Presents a very important<br />
technique for measuring performance, called performance benchmark, explains<br />
how their use can help the developer to have a monitoring of possible changes<br />
in performance in the evolutionary process of the application. Provides an<br />
overview on algorithms and data structures, such as your choice can greatly<br />
influence the speed of a software defined garbage collection, its importance for<br />
proper functioning of the application and provides an insight into the<br />
architecture of the HotSpot virtual machine.
SUMÁRIO<br />
1 – INTRODUÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
1.1 Motivação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
1.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
1.3 Estrutura da Monografia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
2 – DEFINIÇÕES DE PERFORMANCE . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
2.1 <strong>Performance</strong> computacional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
2.2 Utilização de m<strong>em</strong>ória RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
2.3 T<strong>em</strong>po de inicialização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />
2.4 Escalabilidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
2.5 <strong>Performance</strong> Percebida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />
3 – TÉCNICAS PARA MEDIR PERFORMANCE . . . . . . . . . . . . . . . . . . . . 19<br />
3.1 Benchmarking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
3.2 Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />
3.2.1 Usando Hprof e Perfanal. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
4 – RELAÇÃO DE PERFORMANCE COM A IMPLEMENTAÇÃO DE<br />
ALGORITIMOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
5 – RELAÇÃO DE PERFORMANCE COM ESTRUTURAS DE DADOS . . 32<br />
6 – PARTICULARIDADES DO JAVA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
6.1 Garbage collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
6.2 <strong>Java</strong> HotSpot Virtual Machine. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43<br />
CONCLUSÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />
REFERÊNCIAS BIBLIOGRAFICAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />
29
LISTA DE FIGURAS<br />
Figura 1 – Representação da m<strong>em</strong>ória Usada, Livre e o total<br />
perante o HEAP da JVM . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
Figura 2 – Gerenciador de Tarefas do Windows XP. . . . . . . . . . . . . . 14<br />
Figura 3 – Sist<strong>em</strong>a Não Escalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
Figura 4 – Sist<strong>em</strong>a Escalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />
Figura 5 – Comparação entre Des<strong>em</strong>penho computacional e<br />
<strong>Performance</strong> percebida . . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
Figura 6 – Técnica de sincronização. . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
Figura 7 – Simula o teste do cronômetro. . . . . . . . . . . . . . . . . . . . . . . 22<br />
Figura 8 – Recriação da classe teste com o uso da classe<br />
cronômetro. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
Figura 9 – Método recursivo para inverter String . . . . . . . . . . . . . . . . 30<br />
Figura 10 – Exceção lançada após estouro de pilha. . . . . . . . . . . . . . . 30<br />
Figura 11 – Diagrama de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33<br />
Figura 12 – Fábrica de Sincronismo . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
Figura 13 – Benchmark para testar o des<strong>em</strong>penho de diversos tipos<br />
de coleções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
Figura 14 – Arquitetura da maquina virtual . . . . . . . . . . . . . . . . . . . . . . 44<br />
13<br />
18<br />
23<br />
37
1 – Introdução<br />
O presente trabalho irá discorrer sobre des<strong>em</strong>penho de aplicações<br />
desenvolvidas na linguag<strong>em</strong> <strong>Java</strong>, irá definir o que é performance e como ela é<br />
percebida pelo usuário, apresentará boas práticas para o desenvolvedor não<br />
sofrer com perca de des<strong>em</strong>penho, assim como utilizar técnicas e ferramentas<br />
para medir a velocidade da aplicação e se exist<strong>em</strong> objetos ou métodos<br />
consumindo muitos recursos de m<strong>em</strong>ória, apresentará vantagens e<br />
desvantagens de se utilizar algumas estruturas de dados b<strong>em</strong> como algoritmos<br />
e explicará a importância do coletor de lixo na performance final do software.<br />
1.1 Motivação<br />
A motivação para discorrer sobre este assunto é auxiliar aos<br />
desenvolvedores que trabalham com a linguag<strong>em</strong> <strong>Java</strong> a entender os<br />
malefícios de uma aplicação mal estruturada, fazer com que passe a observar<br />
o “todo” e não só uma pequena parte do código quando se está <strong>em</strong> fase de<br />
desenvolvimento, adquirir o hábito de realizar testes de des<strong>em</strong>penho e s<strong>em</strong>pre<br />
buscar a excelência <strong>em</strong> se tratando de velocidade do software.<br />
Hoje <strong>em</strong> dia devido à grande complexidade de funcionalidades<br />
exigidas quando se desenvolve um software, torna-se cada vez mais<br />
importante a otimização do t<strong>em</strong>po de processamento ao realizar tarefas. O que<br />
acontece é que grande parte dos desenvolvedores de softwares ainda não<br />
atentaram para o estudo e analise de como melhorar o t<strong>em</strong>po de<br />
processamento de uma aplicação. Um t<strong>em</strong>po perdido a mais no planejamento<br />
do software para escolher os algoritmos e estruturas de dados adequadas para<br />
cada tarefa pode ser revertido <strong>em</strong> ganho de performance e t<strong>em</strong>po mais a frente<br />
9
no decorrer do projeto, pois reduzirá t<strong>em</strong>po e gastos com refatoração de código<br />
para tentar melhorar o des<strong>em</strong>penho do sist<strong>em</strong>a.<br />
1.2 Objetivos<br />
O objetivo deste trabalho é explicar o que é des<strong>em</strong>penho e qual a<br />
importância de ter uma aplicação com grau satisfatório de performance, assim<br />
como ensinar técnicas para medir a velocidade de métodos, algoritmos e<br />
estrutura de dados usados quando se desenvolve na linguag<strong>em</strong> <strong>Java</strong>.<br />
1.3 Estrutura da Monografia<br />
Esta monografia está dividida <strong>em</strong> seis capítulos. O primeiro traz a<br />
introdução, motivação e a estrutura deste trabalho; o segundo capítulo aborda<br />
a performance, utilização de m<strong>em</strong>ória RAM e como pode-se medir o seu<br />
consumo <strong>em</strong> aplicações <strong>Java</strong>; trata também de t<strong>em</strong>po de inicialização e<br />
escalabilidade b<strong>em</strong> como a performance percebida pelo usuário quando está<br />
usando um sist<strong>em</strong>a; o terceiro capítulo trata de técnicas para medir<br />
des<strong>em</strong>penho quando se está desenvolvendo um sist<strong>em</strong>a, explica o que é<br />
benchmark e como fazer uso dele para melhorar a aplicação, explica a<br />
importância de ferramentas de perfis e apresenta dois tipos que acompanham<br />
a plataforma <strong>Java</strong>; no quarto capítulo é explicado como a escolha errada do<br />
algoritmo pode influenciar no produto final do software; No quinto capítulo<br />
serão apresentadas algumas estruturas de dados utilizadas no <strong>Java</strong>, b<strong>em</strong><br />
como suas vantagens, desvantagens e onde elas pod<strong>em</strong> ser melhor<br />
aproveitadas; por último o sexto capítulo explica como funciona o coletor de<br />
lixo, sua importância e o que ele afeta <strong>em</strong> se tratando de des<strong>em</strong>penho de uma<br />
aplicação; descreve também a máquina virtual Hotspot, desenvolvida pela Sun,<br />
explicando um pouco de sua arquitetura e ensinando alguns parâmetros de<br />
configuração da mesma .<br />
10
2 – Definições de <strong>Performance</strong><br />
2.1 <strong>Performance</strong> Computacional<br />
<strong>Performance</strong> computacional, ou des<strong>em</strong>penho computacional, é um<br />
termo que se refere afim de descrever uma metodologia onde analisa-se o<br />
sist<strong>em</strong>a com o objetivo de melhorar a capacidade de produção, eliminando<br />
ações desnecessárias que reduz<strong>em</strong> a capacidade computacional global do<br />
sist<strong>em</strong>a (MANGAN, 2008, p.2).<br />
Capacidade computacional é á quantidade total de trabalho útil que<br />
pode ser realizado <strong>em</strong> um sist<strong>em</strong>a <strong>em</strong> um determinado período fixo de t<strong>em</strong>po.<br />
São planilhas recalculadas, os relatórios gerados, os trabalhos de impressão, a<br />
rotação de uma imag<strong>em</strong> 3D, ou apenas jogando paciência se o sist<strong>em</strong>a não é<br />
bloqueado (MANGAN, 2008, p.2).<br />
Os algoritmos impl<strong>em</strong>entados pelos desenvolvedores assim como a<br />
estrutura de dados escolhida são alguns dos principais fatores que pod<strong>em</strong><br />
afetar o des<strong>em</strong>penho global de uma aplicação. Acontece que isso é apenas<br />
uma parte no quadro de des<strong>em</strong>penho para qu<strong>em</strong> quer realmente produzir um<br />
software de alta performance.<br />
Para compreender os diferentes tipos de probl<strong>em</strong>as que pod<strong>em</strong> ser<br />
encontrados na hora do desenvolvimento, dev<strong>em</strong>-se considerar todos os<br />
diferentes aspectos do des<strong>em</strong>penho computacional (WILSON, 2001, p.3). Além<br />
da <strong>Performance</strong> computacional t<strong>em</strong>os:<br />
• Utilização da M<strong>em</strong>ória RAM<br />
• T<strong>em</strong>po de inicialização<br />
11
• Escalabilidade<br />
• <strong>Performance</strong> Percebida<br />
2.2 Utilização da M<strong>em</strong>ória RAM<br />
A quantidade de m<strong>em</strong>ória necessária para executar o software pode<br />
ser de uma importância crucial para o des<strong>em</strong>penho global do sist<strong>em</strong>a.<br />
Todos os sist<strong>em</strong>as operacionais modernos fornec<strong>em</strong> um sist<strong>em</strong>a de<br />
m<strong>em</strong>ória virtual onde o espaço <strong>em</strong> disco pode ser utilizado no lugar de uma<br />
RAM física. Contudo mesmo o disco mais rápido, é muito mais lento que o<br />
modulo de m<strong>em</strong>ória mais lento com isso os aplicativos acabam forçando o<br />
Sist<strong>em</strong>a Operacional a ter um fraco des<strong>em</strong>penho na paginação da m<strong>em</strong>ória<br />
virtual.<br />
É muito comum um sist<strong>em</strong>a ter um bom des<strong>em</strong>penho na época de<br />
desenvolvimento e esse des<strong>em</strong>penho cair quando é implantado no cliente<br />
(WILSON, 2001, p.53).<br />
Isso pode ocorrer porque muitas vezes os desenvolvedores<br />
possu<strong>em</strong> uma maquina mais robusta que as do usuário, consequent<strong>em</strong>ente um<br />
software que roda mais confortavelmente na maquina do desenvolvedor, pode<br />
vir a ter um fraco des<strong>em</strong>penho no terminal do usuário.<br />
É preciso desenvolver o software com uma configuração alvo <strong>em</strong><br />
mente, algumas medidas dev<strong>em</strong> ser pensadas antes de começar a<br />
desenvolver algum software, t<strong>em</strong> que se imaginar que a sua aplicação poderá<br />
não ser a única <strong>em</strong> execução na maquina do usuário, usuários geralmente<br />
mantém duas ou três aplicações rodando ao mesmo t<strong>em</strong>po, Não é interessante<br />
que um programa consuma todos os recursos da maquina do usuário.<br />
A API <strong>Java</strong> contém alguns mecanismos que ajudam a descobrir<br />
quanto de m<strong>em</strong>ória RAM seu programa esta consumindo.<br />
12
Exist<strong>em</strong> dois métodos na classe <strong>Java</strong>.lang.Runtime que ajudam a<br />
dar uma idéia de quanta m<strong>em</strong>ória esta sendo consumida, esses métodos<br />
verificam o tamanho do Heap na maquina virtual <strong>Java</strong> (WILSON, 2001, p.53).<br />
• Runtime.totalM<strong>em</strong>ory – retorna o tamanho (<strong>em</strong> bytes) da pilha<br />
usada para alocar os objetos.<br />
• Runtime.freeM<strong>em</strong>ory – retorna a quantidade de m<strong>em</strong>ória que não<br />
esta sendo usada na pilha de objetos<br />
Para descobrir se os objetos estão consumindo muito espaço na<br />
m<strong>em</strong>ória é feito um calculo simples, subtrai-se a m<strong>em</strong>ória livre do total de<br />
m<strong>em</strong>ória como d<strong>em</strong>onstrado na figura 1.<br />
Figura 1: Representação da m<strong>em</strong>ória Usada,<br />
Livre e o total perante o HEAP da JVM.<br />
Fonte: Wilson, 2001<br />
Esse método de inspeção de m<strong>em</strong>ória e útil <strong>em</strong> varias situações,<br />
como para averiguar o uso da pilha do programa <strong>em</strong> intervalos regulares de<br />
t<strong>em</strong>po a fim de descobrir se está ocorrendo vazamento de m<strong>em</strong>ória se o uso<br />
da pilha fica aumentando ao longo do t<strong>em</strong>po.<br />
13
O <strong>Java</strong> não fornece nenhum método para verificar a velocidade do<br />
programa, para medir com precisão a velocidade do seu aplicativo <strong>Java</strong> é<br />
preciso apelar para utilitários específicos de uso do Sist<strong>em</strong>a Operacional.<br />
O Windows XP, por ex<strong>em</strong>plo, fornece uma ferramenta chamada<br />
Gerenciador de tarefas que nos fornece informações do uso de m<strong>em</strong>ória pelos<br />
processos que estão <strong>em</strong> execução (ver Figura 2).<br />
Figura 2: Gerenciador de Tarefas do Windows XP<br />
Fonte: Elaborado pelo autor<br />
Vários outros fatores contribu<strong>em</strong> também para o des<strong>em</strong>penho do<br />
sist<strong>em</strong>a e um melhor aproveitamento da m<strong>em</strong>ória e dev<strong>em</strong> ser analisados com<br />
muita calma pelo desenvolvedor (WILSON, 2001,p.53).<br />
• Objetos<br />
• Classes<br />
• Tópicos<br />
• Estrutura Nativa de Dados<br />
• Código Nativo<br />
14
O consumo de m<strong>em</strong>ória relativa desses itens varia de acordo com a<br />
aplicação, plataforma ou ambiente de execução, porém objetos e classes<br />
requ<strong>em</strong> um pouco mais de atenção, pois normalmente são os que consom<strong>em</strong><br />
mais m<strong>em</strong>ória, o seu consumo varia de aplicativo para aplicativo.<br />
Por ex<strong>em</strong>plo, aplicações desktop que utilizam interfaces gráficas, as<br />
classes tend<strong>em</strong> a utilizar mais a m<strong>em</strong>ória da maquina-cliente pelo fato de que<br />
para iniciar uma interface gráfica sejam necessárias várias classes, já uma<br />
aplicação web utiliza a m<strong>em</strong>ória mais com objetos, pois geralmente criamos<br />
mais objetos para trafegar<strong>em</strong> as informações entre a Web (WILSON, 2001,p.53).<br />
2.3 T<strong>em</strong>po de Inicialização<br />
Historicamente os sist<strong>em</strong>as desenvolvidos <strong>em</strong> <strong>Java</strong> possu<strong>em</strong> um<br />
t<strong>em</strong>po de inicialização mais lento (WILSON, 2001, p.24).<br />
O t<strong>em</strong>po de inicialização de um aplicativo é medido pelo t<strong>em</strong>po que<br />
ele leva para levantar o serviço, carregar e ficar pronto para o usuário utilizar,<br />
isso inclui tanto o t<strong>em</strong>po de inicialização da JVM como do aplicativo <strong>Java</strong> <strong>em</strong> si.<br />
Para medir o t<strong>em</strong>po de inicialização de uma aplicação <strong>Java</strong> o<br />
desenvolvedor pode fazer uso de dois métodos contidos na API <strong>Java</strong> (ORACLE,<br />
2009, p.26-3).<br />
• Syst<strong>em</strong>.nanoTime(): retorna um valor <strong>em</strong> nano segundos.<br />
(recupera o valor do Sist<strong>em</strong>a Operacional).<br />
• Syst<strong>em</strong>.currentTimeMillis(): retorna o t<strong>em</strong>po atual <strong>em</strong><br />
milissegundos.<br />
O Tamanho da pilha também influencia no t<strong>em</strong>po de inicialização da<br />
JVM e da aplicação, isso porque a máquina virtual reserva um espaço na<br />
m<strong>em</strong>ória para o tamanho máximo da pilha (-Xmx) e compromete a m<strong>em</strong>ória<br />
com o tamanho da pilha inicial (-Xms).(ORACLE, 2009, p. 10-2).<br />
15
Para aplicações de grande porte é inevitável ter essas duas<br />
variáveis definidas com valores muito altos, mas para uma aplicação de<br />
pequeno ou médio porte valores altos pod<strong>em</strong> ocasionar uma lentidão<br />
desnecessária na inicialização da máquina virtual. Por outro lado se a pilha<br />
está definida com um valor muito pequeno ela vai ocasionar uma sobrecarga<br />
na inicialização da maquina virtual, consequent<strong>em</strong>ente forçará a mesma a<br />
realizar constantes coletas de lixo ate que a pilha tenha crescido a um tamanho<br />
razoável.<br />
2.4 Escalabilidade<br />
Escalabilidade é a capacidade de o sist<strong>em</strong>a permanecer operando<br />
de forma efetiva mesmo diante de um aumento significativo do número de<br />
usuários ou/e de recursos disponíveis. É uma característica almejada por todos<br />
que estão desenvolvendo um sist<strong>em</strong>a e está ligada ao des<strong>em</strong>penho da<br />
aplicação (MOREIRA, 2009, p.3).<br />
A aplicação pode ter um ótimo des<strong>em</strong>penho quando enfrenta a<br />
concorrência de 100 acessos simultâneos mais será que ela conseguirá<br />
suportar um aumento de acessos na ord<strong>em</strong> 100 vezes. As figuras 3 e 4<br />
mostram a diferença de t<strong>em</strong>po entre um sist<strong>em</strong>a escalar e um não escalar.<br />
Figura 3: Sist<strong>em</strong>a Não Escalar<br />
Fonte: Wilson, 2001<br />
16
Figura 4: Sist<strong>em</strong>a Escalar<br />
Fonte: Wilson, 2001<br />
O t<strong>em</strong>po de resposta sofre um aumento quase que exponencial<br />
quando o número de usuários do sist<strong>em</strong>a cresce <strong>em</strong> uma aplicação Não<br />
Escalar o que torna praticamente inviável o seu uso. (figura 3)<br />
Já <strong>em</strong> um sist<strong>em</strong>a Escalar, o aumento no t<strong>em</strong>po de resposta é b<strong>em</strong><br />
menor, devido à sua característica de se readaptar de acordo com a d<strong>em</strong>anda<br />
(figura 4).<br />
Faz-se necessário antes de implantar um sist<strong>em</strong>a no cliente, s<strong>em</strong>pre<br />
submetê-lo a testes de Des<strong>em</strong>penho com uma carga aproximada de acessos<br />
concorrentes para que se tenha uma real noção de seu des<strong>em</strong>penho quando o<br />
mesmo realmente estiver <strong>em</strong> pleno funcionamento.<br />
É importante estar ciente dos principais probl<strong>em</strong>as de escalabilidade<br />
e desenhar um sist<strong>em</strong>a que esteja preparado para um eventual crescimento<br />
futuro, exist<strong>em</strong> algumas boas praticas no <strong>Java</strong> que ajudam a construir uma<br />
aplicação preparada para expansão um deles é o encapsulamento que Craig<br />
Larman (2003) define como:<br />
“um mecanismo usado para ocultar os dados, a estrutura interna e<br />
detalhes de impl<strong>em</strong>entação de um objeto”<br />
17
O encapsulamento propõe que se isole a estrutura interna dos<br />
Objetos do resto do programa, por isso seu uso é muito aconselhado <strong>em</strong><br />
sist<strong>em</strong>as escalares e de alto des<strong>em</strong>penho, a vantag<strong>em</strong> que ele traz é de se<br />
poder avaliar rapidamente diferentes algoritmos e estruturas de dados, como<br />
também evoluir facilmente o projeto para acomodar requisitos novos ou<br />
alterados (WILSON, 2001, p.12).<br />
2.5 <strong>Performance</strong> Percebida<br />
<strong>Performance</strong> percebida esta ligada com a percepção do ser humano<br />
sobre o des<strong>em</strong>penho do software, muitas pessoas da área de tecnologia da<br />
informação confund<strong>em</strong> des<strong>em</strong>penho computacional com performance<br />
percebida, esses são dois estudos diferentes enquanto o des<strong>em</strong>penho<br />
computacional age mais <strong>em</strong> cima do des<strong>em</strong>penho do software(apesar de<br />
poder afetar o usuário <strong>em</strong> si), a percepção de performance pensa somente no<br />
usuário (MANGAN, 2008, p2). O processo de reflexão e análise do des<strong>em</strong>penho<br />
percebido t<strong>em</strong> vários objetivos. A figura 5 retrata as diferenças entre<br />
des<strong>em</strong>penho computacional e performance percebida.<br />
Figura 5: Comparação entre Des<strong>em</strong>penho computacional<br />
e <strong>Performance</strong> percebida<br />
Fonte: Mangan, 2008<br />
18
3 – Técnicas para Medir <strong>Performance</strong><br />
3.1. Benchmarking<br />
Benchmarking é o processo de comparação de operações de uma<br />
maneira que produza resultados quantitativos. Ele des<strong>em</strong>penha um papel<br />
fundamental para garantir uma boa execução do software. Os processos a<br />
ser<strong>em</strong> comparados pod<strong>em</strong> ser desde dois algoritmos diferentes que produz<strong>em</strong><br />
o mesmo resultado, ou duas maquinas virtuais executando o mesmo código<br />
(WILSON, 2001, p.21).<br />
O aspecto fundamental do benchmarking é a comparação. Um único<br />
resultado produzido por ele não t<strong>em</strong> muito valor, só é válido quando ocorre a<br />
comparação. Benchmarks tipicamente med<strong>em</strong> a quantidade de t<strong>em</strong>po que se<br />
leva para realizar uma tarefa específica, mas também pod<strong>em</strong> ser usadas para<br />
medir outras variáveis tais como a quantidade de m<strong>em</strong>ória necessária para<br />
realizar determinada tarefa.<br />
Existe uma técnica de benchmarking simples e útil que pode ser<br />
usada para medir o des<strong>em</strong>penho de um software. Chama-se Cronômetro<br />
Benchmarking. Como o próprio nome já sugere, essa técnica consiste <strong>em</strong><br />
medir a performance com um cronômetro na mão e apesar de não ter a<br />
precisão de milissegundos, ela é bastante útil <strong>em</strong> diversas situações, como as<br />
listadas abaixo (WILSON, 2001, p.21).<br />
• Medir quanto t<strong>em</strong>po d<strong>em</strong>ora ao lançar um aplicativo<br />
• Medir o t<strong>em</strong>po que se leva para abrir um documento grande<br />
• Medir o t<strong>em</strong>po que se leva para percorrer uma tabela muito<br />
grande de dados<br />
19
• Medir quanto t<strong>em</strong>po leva para executar uma consulta de uma<br />
tabela de banco de dados complexa.<br />
A tabela abaixo faz um comparativo das vantagens e desvantagens<br />
de usar o cronometro benchmarking na medição de des<strong>em</strong>penho de um<br />
software:<br />
Prós Contras<br />
Fácil Pode ser Impreciso<br />
Não precisa modificar fonte código ou<br />
a utilização de instrumentos<br />
complexos de software<br />
Difícil de automatizar os testes<br />
Não vai distorcer os resultados Sujeito a erro humano<br />
Outra técnica recomendada para uma ampla variedade de situações<br />
é a de adicionar a funcionalidade de sincronismo ao código que está sendo<br />
avaliado. No <strong>Java</strong> existe a classe java.lang.Syst<strong>em</strong> que cont<strong>em</strong> vários métodos<br />
estáticos uteis incluindo um método chamado currentTimeMillis. Esse método<br />
retorna uma variável do tipo long que contém o número de milissegundos que<br />
se passaram desde a meia noite do dia 01 de janeiro de 1970. Portanto para<br />
usar esse método para descobrir quanto t<strong>em</strong>po uma determinada parte do<br />
código d<strong>em</strong>ora a ser executada, é necessário armazenar o t<strong>em</strong>po antes e após<br />
a seção de código que se quer testar, e depois subtrair o t<strong>em</strong>po final do inicial.<br />
A figura 6 mostra o ex<strong>em</strong>plo dessa técnica <strong>em</strong> uma classe <strong>Java</strong> (WILSON, 2001,<br />
p.21).<br />
20
Figura 6: Técnica de sincronização<br />
Fonte: Elaborado pelo autor<br />
Essa técnica essencialmente é o mesmo que usar um cronômetro<br />
exceto que o computador inicia e para o relógio automaticamente e também faz<br />
com que o teste fique automatizado, o que acaba reduzindo o percentual de<br />
erro no resultado do teste.<br />
Uma boa prática para esse tipo de técnica consiste no<br />
encapsulamento, ou seja, criar uma classe que <strong>em</strong>ule o comportamento do<br />
cronômetro (figura 7) e fazendo uso dela na parte de código que se deseja<br />
testar, isso facilitará a vida do desenvolvedor al<strong>em</strong> de seguir um dos princípios<br />
da Orientação a Objeto que é reutilização de código, pois não terá que replicar<br />
o mesmo tipo de teste <strong>em</strong> diferentes partes do programa e também exclui<br />
possíveis erros que poderiam vir a acontecer por desatenção na hora de<br />
escrever o teste. A figura 8 d<strong>em</strong>onstra como ficaria o teste anterior, agora<br />
fazendo uso de uma classe cronômetro.<br />
21
Figura 7: Simula o teste do cronômetro<br />
Fonte: Elaborado pelo autor<br />
22
Figura 8: Recriação da classe teste com o uso da classe cronômetro<br />
Fonte:Elaborado pelo autor<br />
Exist<strong>em</strong> várias ferramentas de benchmarks criados pelas<br />
comunidades de desenvolvedores <strong>Java</strong>, projetados para comparar<br />
impl<strong>em</strong>entações <strong>em</strong> t<strong>em</strong>po de execução que pod<strong>em</strong> ser uteis na hora de testar<br />
o des<strong>em</strong>penho de um software. Alguns ex<strong>em</strong>plos dessas soluções são<br />
(WILSON, 2001, p.21):<br />
• SpecJvm2008 – desenvolvido pela Standard <strong>Performance</strong><br />
Evaluation Corporation (SPEC) é utilizado para medir o<br />
des<strong>em</strong>penho de diferentes maquinas virtuais <strong>Java</strong>.<br />
• VolanoMark – desenvolvido pela Volano, permite determinar a<br />
conexão e as limitações de des<strong>em</strong>penho do hardware, sist<strong>em</strong>a<br />
operacional e plataforma <strong>Java</strong>.<br />
• SciMark – desenvolvido por Roldan Pozo e Bruce Miller , t<strong>em</strong><br />
como finalidade medir o des<strong>em</strong>penho de códigos numéricos que<br />
ocorr<strong>em</strong> na engenharia e aplicações cientificas.<br />
• CaffeineMark – desenvolvido pela Pendragon Software<br />
Corporation, consiste <strong>em</strong> uma serie de testes que med<strong>em</strong> a<br />
velocidade dos programas <strong>Java</strong> rodando <strong>em</strong> vários hardwares e<br />
softwares de configurações diferente.<br />
23
Embora essas soluções sejam ótimas para avaliar a aplicação <strong>em</strong><br />
t<strong>em</strong>po de execução, faz-se necessário a criação de benchmarks específicos<br />
para avaliar o des<strong>em</strong>penho do software, ou seja, que test<strong>em</strong> seu próprio<br />
código, as vantagens desse tipo de abordag<strong>em</strong> são que se pode comparar<br />
des<strong>em</strong>penho de soluções alternativas, acompanhar o des<strong>em</strong>penho e realizar a<br />
analise de tendência ao longo do ciclo de desenvolvimento.<br />
A comparação, aliás, é o uso mais óbvio dos benchmarks<br />
personalizados, por ex<strong>em</strong>plo, quando o desenvolvedor precisa escolher entre<br />
dois algoritmos para impl<strong>em</strong>entar determinada função, então ele pode criar um<br />
ponto de referência e comparar as duas soluções.<br />
Uma das grandes vantagens dos benchmarkings é que se pode<br />
acompanhar e analisar as tendências do programa ao longo do<br />
desenvolvimento, com isso ao adicionarmos novas funcionalidades ou<br />
corrigirmos erros encontrados no meio desse processo, pode-se facilmente<br />
descobrir o quanto a aplicação ficou mais lenta e ter o real controle de onde<br />
isso está ocorrendo.<br />
Benchmarks pod<strong>em</strong> ser divididos <strong>em</strong> duas categorias, micro-<br />
benchmarks e macro-benchmarks (WILSON, 2001, p.21):<br />
• Micro-Benchmarks – são micro-pontos de referência que muitas<br />
vezes pod<strong>em</strong> ser escritos <strong>em</strong> poucas linhas de código e são<br />
tipicamente muito fáceis de descrever.<br />
• Macro-Benchmarks – Realizam testes no sist<strong>em</strong>a como o usuário<br />
final vai vê-lo. Para construí-lo é preciso entender como o cliente<br />
irá utilizar o produto.<br />
Saber analisar e interpretar os resultados gerados nos testes é<br />
essencial, é preciso ter <strong>em</strong> mente que eles geralmente variam de execução<br />
para execução, para facilitar a analise é recomendável realizar diversas tiradas<br />
de t<strong>em</strong>po, após colher os dados com t<strong>em</strong>pos diferentes precisa-se realizar a<br />
analise estatística, exist<strong>em</strong> muitos tipos de estatísticas que pod<strong>em</strong> ser uteis,<br />
24
mas é recomendável que se determine três números chaves, para o melhor<br />
caso, pior caso e processo médio, para informar o pior caso basta pegar o pior<br />
t<strong>em</strong>po, o melhor caso pega-se o melhor t<strong>em</strong>po e o processo médio tira-se uma<br />
media do t<strong>em</strong>pos colhidos. Como benchmark sustenta-se <strong>em</strong> comparações<br />
deve-se fazê-las ao logo do desenvolvimento do sist<strong>em</strong>a para que possa<br />
acompanhar as mudanças de des<strong>em</strong>penho.<br />
3.2. Profiling<br />
Profiling é uma forma dinâmica de analisar um determinado<br />
programa, ou seja, é uma forma de investigar o comportamento de um<br />
programa usando informações recolhidas após a execução do mesmo. O<br />
objetivo dessa análise é detectar quais seções de um programa precisam ser<br />
otimizadas, seja para aumentar a velocidade geral ou diminuir o uso da<br />
m<strong>em</strong>ória, ou ás vezes ambos.<br />
Ferramentas de profiling dev<strong>em</strong> ser capazes de responder algumas<br />
perguntas, tais como: quais os métodos que são utilizados com maior<br />
frequência, quais métodos estão chamando os métodos mais utilizados, quais<br />
o métodos estão alocando mais m<strong>em</strong>ória, qual a percentag<strong>em</strong> de t<strong>em</strong>po que<br />
cada método e utilizado. Essas ferramentas são na maioria das vezes ricas <strong>em</strong><br />
interfaces e permit<strong>em</strong> que possa escolher que tipo de teste deseja-se realizar.<br />
Profiling pode ajudar ao desenvolvedor identificar se existe algum<br />
método critico na aplicação, se este esta tomando a maior parte do t<strong>em</strong>po de<br />
processamento da mesma, então o desenvolvedor poderá direcionar seu<br />
esforço para melhorar o des<strong>em</strong>penho do método avaliado (WILSON, 2001, p.21).<br />
Exist<strong>em</strong> dois tipos de abordagens para otimizar a aplicação a qual o<br />
desenvolvedor pode fazer uso quando descobre onde esta ocorrendo a queda<br />
de des<strong>em</strong>penho do sist<strong>em</strong>a (WILSON, 2001, p.21).<br />
• Fazer com que métodos que sejam utilizados com maior<br />
frequência torn<strong>em</strong>-se mais rápidos<br />
25
• Fazer com que métodos mais lentos sejam chamados com menor<br />
frequência.<br />
Muitas vezes programadores part<strong>em</strong> logo para a primeira alternativa,<br />
sendo que às vezes é mais fácil descobrir o porquê do método ser chamado<br />
com muita freqüência e com isso tentar diminuir o numero de vezes que esse<br />
método é acessado.<br />
Ferramentas de profiling são interessantes para descobrir o quanto<br />
de objetos seu programa t<strong>em</strong>, e quanto os mesmos estão consumindo de<br />
m<strong>em</strong>ória, fazendo com que o programador tente minimizar a criação de<br />
objetos, muitas vezes a uma relação entre métodos que utilizam muitos objetos<br />
e métodos que são chamados várias vezes na aplicação, s<strong>em</strong>pre é bom<br />
verificar se todos os objetos criados no método são realmente necessários. Um<br />
ex<strong>em</strong>plo comum de criação de muitos objetos <strong>em</strong> um método e que com o uso<br />
dessas ferramentas o programador pode minimizar é quando um método cria<br />
um objeto dentro de um laço de repetição, a cada interação será criado um<br />
novo objeto, e esse vai sendo alocado na pilha de objetos da jvm fazendo com<br />
que o des<strong>em</strong>penho da aplicação caia, podendo gerar até um estouro de pilha,<br />
movendo a criação para fora do laço faz com que o consumo de m<strong>em</strong>ória seja<br />
reduzido.<br />
O vazamento de m<strong>em</strong>ória também é um dos probl<strong>em</strong>as críticos<br />
quando se está desenvolvendo um sist<strong>em</strong>a, vazamento de m<strong>em</strong>ória ocorre<br />
quando a m<strong>em</strong>ória é alocada, mas não é liberada, <strong>em</strong>bora a maquina virtual<br />
<strong>Java</strong> seja responsável pela liberação de m<strong>em</strong>ória através do garbage collector,<br />
a mesma não garante que horas isso ocorrerá, o que pode atrapalhar o<br />
des<strong>em</strong>penho do sist<strong>em</strong>a (WILSON, 2001, p.21).<br />
O isolamento do vazamento de m<strong>em</strong>ória pode ser uma tarefa muito<br />
difícil, é ai que o uso de profiling pode tornar-se uma arma a favor do<br />
desenvolvedor, as ferramentas são bastante uteis para:<br />
• Acompanhar o numero de instâncias de todas as classes <strong>em</strong><br />
determinado momento.<br />
26
• Isolar um determinado objeto e ver todas as referências que<br />
apontam pra ele.<br />
• Coleta manual de lixo perdido.<br />
A primeira etapa para isolar o vazamento é colocar o programa <strong>em</strong><br />
um estado de stress, ou seja, testá-lo com sua capacidade máxima, após isso,<br />
deve-se realizar varias operações para certificar-se se todos os t<strong>em</strong>pos gastos<br />
na inicialização foram computados e que todos os objetos necessários foram<br />
carregados, após isso retorna o programa ao estado normal, e faz-se um<br />
comparativo de des<strong>em</strong>penho quando o mesmo estava submetido a sua<br />
capacidade máxima. Depois, deve-se usar uma ferramenta de análise para<br />
determinar o numero de anomalias existentes <strong>em</strong> cada classe, com o resultado<br />
da analise <strong>em</strong> mãos deve-se fazer o uso da ferramenta de profiling para<br />
processar todo o lixo disponível. Então, volta-se a usar o sist<strong>em</strong>a <strong>em</strong> modo de<br />
stress e depois <strong>em</strong> modo normal, para que sejam feitas novas comparações,<br />
se terminado os testes os t<strong>em</strong>pos de processamento e des<strong>em</strong>penho<br />
continuar<strong>em</strong> quase iguais é sinal que a limpeza de lixo foi b<strong>em</strong> sucedida.<br />
3.2.1 Usando HPROF e PERFANAL<br />
Hprof é uma ferramenta de profiling para criação de estatísticas<br />
sobre o des<strong>em</strong>penho da CPU e da pilha, ele é um agente incorporado a JVM<br />
que é carregado dinamicamente através de linha de comando na sua<br />
inicialização e torna-se processo da mesma. Ao fornecer opções HPROF na<br />
inicialização, os usuários pod<strong>em</strong> solicitar vários tipos de pilha e / ou recursos<br />
de CPU profiling HPROF. Os dados gerados pod<strong>em</strong> ser <strong>em</strong> forma de texto ou<br />
binário, e pod<strong>em</strong> ser usados para rastrear e isolar probl<strong>em</strong>as de des<strong>em</strong>penho<br />
que envolve o uso de m<strong>em</strong>ória e de código ineficiente. O arquivo de formato<br />
binário do HPROF pode ser usado com ferramentas como HAT (Heap Analysis<br />
Toll) para procurar os objetos alocados no HEAP (O'HAIR, 2004).<br />
A partir da versão cinco do J2SE o HPROF passou a ser<br />
impl<strong>em</strong>entado na nova JVM TI (<strong>Java</strong> Virtual Machine Tool Interface), ele é<br />
27
capaz de apresentar estatísticas sobre alocação da pilha e monitorar os perfis<br />
de contenção.<br />
Perfanal é uma ferramenta baseada <strong>em</strong> GUI (Interface Gráfica para<br />
Usuário) para analisar o des<strong>em</strong>penho de aplicações na plataforma <strong>Java</strong>, ele é<br />
usado para identificar probl<strong>em</strong>as de des<strong>em</strong>penho no código e localizar o código<br />
que precise de ajustes, ela é uma ferramenta livre, licenciada pela GPL<br />
(MEYERS, 2000).<br />
O Perfanal t<strong>em</strong> a característica de simplificar bastante a analise do<br />
des<strong>em</strong>penho por que ele interpreta os dados do perfil analisado e informa o<br />
custo total dos métodos, ele apresenta os resultados <strong>em</strong> forma de gráfico o que<br />
ajuda a análise.<br />
28
4 – Relação de <strong>Performance</strong> com Impl<strong>em</strong>entação de<br />
Algoritmos<br />
Escolher o algoritmo correto é um fator primordial para obter-se um<br />
grande des<strong>em</strong>penho da aplicação, se escolher o algoritmo errado todo o ajuste<br />
feito por menor que seja não produzirá ganho de des<strong>em</strong>penho satisfatório. Um<br />
algoritmo pode ter diferentes comportamentos para diferentes aplicações, ele<br />
pode ser eficiente para algumas situações e deficiente para outras. Não<br />
exist<strong>em</strong> algoritmos que sejam bons para todos os tipos de situações, deve-se<br />
analisar o algoritmo de acordo com o objetivo que se deseja alcançar e<br />
escolher a solução que proporcionar melhores resultados. Para facilitar esse<br />
tipo de escolha deve-se fazer uso de técnicas para comparação de soluções<br />
como a já mencionada Benchmark, após decidir qual algoritmo usar, deve-se<br />
levar o espaço do probl<strong>em</strong>a <strong>em</strong> consideração. Espaço do probl<strong>em</strong>a é um<br />
conjunto de probl<strong>em</strong>as com os quais o algoritmo será apresentado, <strong>em</strong> outras<br />
palavras são as situações com o qual o algoritimo irá se deparar para que<br />
consiga resolver um determinado probl<strong>em</strong>a. Muitas vezes pode-se atingir a<br />
solução mais eficiente restringindo o algoritmo a tratar apenas o probl<strong>em</strong>a do<br />
espaço definido <strong>em</strong> vez de usar o algoritmo mais geral, ou seja, o que o<br />
programa não vai fazer é tão importante quanto ao que o programa faz.<br />
Algoritmos recursivos pod<strong>em</strong> ser usados <strong>em</strong> muitos casos para<br />
resolver probl<strong>em</strong>as lineares complexos, mas ela pode ser uma pratica não<br />
muito recomendada <strong>em</strong> se tratando de algoritmos com muitas chamadas a<br />
função recursiva, com isso ocorre o aumento de consumo de m<strong>em</strong>ória e<br />
consequent<strong>em</strong>ente a performance da aplicação diminui.<br />
29
Cada chamada sucessiva de uma função recursiva cria um novo<br />
quadro de pilha, se a função é chamada muitas vezes também pode fazer com<br />
que o programa funcione com a m<strong>em</strong>ória sobrecarregada. O ex<strong>em</strong>plo disso é o<br />
algorítimo usado para inverter uma string (figura 9)<br />
Figura 9: Método recursivo para inverter String<br />
Fonte: Elaborado pelo autor<br />
Se passarmos uma seqüência muito grande de strings para o<br />
algoritmo inverter ele pode gerar um erro de estouro de pilha<br />
(stackoverflowerror) conforme a figura 10.<br />
Figura 10: Exceção lançada após estouro de pilha<br />
Fonte: Laskowski, 2010<br />
Algoritmos não são apenas soluções b<strong>em</strong> definidas para tarefas<br />
normais, ao construir uma aplicação o desenvolvedor deve s<strong>em</strong>pre perder um<br />
t<strong>em</strong>po a mais para analisar o algoritmo correto que utilizará, pois a escolha<br />
30
errada no começo pode fazer com que todo o sist<strong>em</strong>a tenha um des<strong>em</strong>penho<br />
não satisfatório.<br />
31
5 – Relação de <strong>Performance</strong> com Estruturas de<br />
Dados<br />
A seleção de estrutura de dados adequada é tão importante quanto<br />
a escolha do algoritmo. As estruturas de dados são normalmente conhecidas<br />
como vetores, listas, filas etc. A plataforma <strong>Java</strong> possui suas próprias<br />
impl<strong>em</strong>entações para algumas estruturas tais como ArrayList (listas), LinkedList<br />
(filas) SortedList( lista ordenada). Todas essas classes são impl<strong>em</strong>entações da<br />
interface Collection (coleções).<br />
Coleção é um objeto que agrupa múltiplos el<strong>em</strong>entos <strong>em</strong> uma única<br />
unidade e são usadas para armazenar, recuperar e manipular dados. Ela<br />
também é usada para transmitir dados a partir de um método para<br />
outro. Coleções normalmente representam itens de dados que formam um<br />
grupo natural, tais como (WILSON, 2001, p.122).<br />
• Coleção de carros <strong>em</strong> uma concessionária.<br />
• Coleção de livros de uma biblioteca.<br />
• Coleção de animais <strong>em</strong> um zoológico.<br />
A sua estrutura de uma coleção é composta de uma arquitetura<br />
unificada para representar e manipular coleções trazendo a vantag<strong>em</strong> de<br />
reduzir o esforço de programação, aumentando a performance. A estrutura foi<br />
projetada para:<br />
• Promover o reuso de software.<br />
• Reduzir o esforço na concepção e de aprender novas APIs.<br />
• Habilitar a coleta de dados a ser manipulado independente da sua<br />
representação.<br />
• Facilitar a interoperabilidade entre APIs independentes.<br />
32
Coleções oferec<strong>em</strong> uma alta performance aliada com uma<br />
impl<strong>em</strong>entação de ótima qualidade das estruturas de dados, coleções ajudam a<br />
melhorar a qualidade e des<strong>em</strong>penho do software (WILSON, 2001, p.122). Por<br />
ser uma estrutura pronta e desenvolvida para que o programador não utilize<br />
seu t<strong>em</strong>po impl<strong>em</strong>entando funcionalidades para melhorar o des<strong>em</strong>penho, ou<br />
seja, reescrevendo uma estrutura que já existe e está otimizada. O uso dela<br />
acaba facilitando a vida do desenvolvedor para que ele utilize o seu t<strong>em</strong>po para<br />
dedicar-se a melhoria da qualidade e des<strong>em</strong>penho do resto da aplicação. Sua<br />
estrutura e baseada <strong>em</strong> seis interfaces como d<strong>em</strong>onstrado no diagrama de<br />
classes contido na figura 11.<br />
Figura 11: Diagrama de classe<br />
Fonte: Elaborado pelo autor<br />
Cada tipo de estrutura de dados se adéqua mais a determinado tipo<br />
de tarefa, entender o que cada estrutura de dados faz ajuda ao desenvolvedor<br />
na escolha de qual será a melhor para resolver seu probl<strong>em</strong>a,<br />
conseqüent<strong>em</strong>ente ajudará a obter um maior des<strong>em</strong>penho da aplicação. Para<br />
algumas interfaces, a estrutura oferece múltiplas impl<strong>em</strong>entações concretas.<br />
A lista (List) é uma interface que estende de Coleção, ela é<br />
ordenada e pode conter el<strong>em</strong>entos repetidos, ao usar uma lista o<br />
desenvolvedor t<strong>em</strong> o pleno controle sobre onde cada el<strong>em</strong>ento é inserido,<br />
33
pode-se acessar os el<strong>em</strong>entos de uma lista só pelo seu índice (WILSON, 2001,<br />
p.122).<br />
Muitas vezes quando se deseja utilizar uma lista no <strong>Java</strong> faz-se o<br />
uso do ArrayList por ser bastante rápido <strong>em</strong> algumas situações como itera-la e<br />
por não ter de atribuir um objeto do nó para cada el<strong>em</strong>ento da lista, ele usa o<br />
método nativo Syst<strong>em</strong>.arraycopy para mover vários el<strong>em</strong>entos<br />
simultaneamente. Um ArrayList é essencialmente um vetor s<strong>em</strong> o overhead de<br />
sincronização (WILSON, 2001, p.122).<br />
LinkedList é outro tipo de impl<strong>em</strong>entação da classe List e usado para<br />
qu<strong>em</strong> deseja adicionar el<strong>em</strong>entos no inicio da lista ou iterar a lista e excluir<br />
el<strong>em</strong>entos do seu interior, o t<strong>em</strong>po que se leva para percorrer uma lista e maior<br />
que no ArrayList, <strong>em</strong> compensação ele ganha quando deseja-se inserir e<br />
excluir el<strong>em</strong>entos <strong>em</strong> qualquer local da lista (WILSON, 2001, p.122). A melhor<br />
maneira de escolher qual impl<strong>em</strong>entação irá usar e criar um benchmark<br />
idêntico ao probl<strong>em</strong>a encontrado no seu programa e medir o t<strong>em</strong>po gasto para<br />
realizar a operação.<br />
Um Set é uma coleção que não pode conter el<strong>em</strong>entos duplicados,<br />
ela é uma abstração mat<strong>em</strong>ática dos conjuntos. Exist<strong>em</strong> duas classes que<br />
estend<strong>em</strong> da interface Set, que são HashSet e SortedSet a diferença é que a<br />
HashSet é b<strong>em</strong> mais rápida mas não garante ordenação, se precisar de<br />
garantia de ordenação deve-se usar a classe SortedSet ou TreeSet (WILSON,<br />
2001, p.122).<br />
Recomenda-se ao trabalhar com HashSet que escolha uma<br />
capacidade inicial compatível com a atividade que deseja-se realizar, se<br />
escolher uma capacidade muito alta pode-se desperdiçar espaço b<strong>em</strong> como<br />
t<strong>em</strong>po. A capacidade inicial é de 101 el<strong>em</strong>entos, no geral costuma-se escolher<br />
uma capacidade duas vezes o tamanho que espera-se que o conjunto cresça<br />
(WILSON, 2001, p.122).<br />
34
HashSets possu<strong>em</strong> um parâmetro de ajuste, chamado de fator de<br />
carga. Esta é uma medida de quanto é permitido que o HashSet obtenha de<br />
sua capacidade para aumentá-la automaticamente. Quando o número de<br />
inscrições excede o produto do fator de carga e da capacidade atual, a<br />
capacidade será dobrada. Geralmente, o fator de carga padrão (0,75) oferece<br />
uma boa performance levando <strong>em</strong> conta custos e espaço de t<strong>em</strong>po (WILSON,<br />
2001, p.122).<br />
Exist<strong>em</strong> duas classes no <strong>Java</strong> que são sincronizadas a HashTable e<br />
a Vector, por padrão as classes de coleções não são sincronizadas fazendo<br />
com que o acesso a essa estrutura seja mais rápido quando se usa Threads no<br />
mesmo ambiente. Já as coleções sincronizadas faz<strong>em</strong> uso do conjunto de<br />
classes Wrapper.<br />
Essas classes adicionam funcionalidades a impl<strong>em</strong>entação padrão<br />
das coleções, as impl<strong>em</strong>entações Wrapper são anônimas, fornec<strong>em</strong> um<br />
método estático que funciona como uma fabrica de sincronismo como pode ser<br />
visto na figura 12.<br />
public static Collection synchronizedCollection(Collection c);<br />
public static Set synchronizedSet(Set s);<br />
public static List synchronizedList(List list);<br />
public static Map synchronizedMap(Map m);<br />
public static SortedSet synchronizedSortedSet(SortedSet s);<br />
Figura 12: Fábrica de Sincronismo<br />
Fonte: Wilson, 2001<br />
Cada método retorna uma fábrica sincronizada que é apoiada por<br />
uma instância do tipo da instância escolhida. Quando se deseja iterar sobre<br />
uma coleção sincronizada o desenvolvedor acaba tendo que sincronizar<br />
manualmente a operação isso ocorre porque a iteração é realizada através de<br />
varias chamadas para a coleção e essas chamadas t<strong>em</strong> que ser composta por<br />
uma única operação atômica como no ex<strong>em</strong>plo abaixo, se o desenvolvedor não<br />
utilizar essa técnica a iteração pode resultar <strong>em</strong> um comportamento não-<br />
determinístico.<br />
35
A estrutura de coleções fornece alguns frameworks de algoritmos.<br />
Do ponto de vista de des<strong>em</strong>penho exist<strong>em</strong> dois: sort e binarySeach. Classificar<br />
e pesquisar são tarefas comuns que pod<strong>em</strong> assumir uma grande parte do<br />
t<strong>em</strong>po. A estrutura das coleções fornece impl<strong>em</strong>entações b<strong>em</strong>-testadas dessas<br />
tarefas e que possu<strong>em</strong> as características de des<strong>em</strong>penho documentadas.<br />
Essas impl<strong>em</strong>entações são acessados através de algoritmo estático.<br />
“Framework é um conjunto de classes que colaboram para<br />
realizar uma responsabilidade para um domínio de um subsist<strong>em</strong>a da<br />
aplicação” (Fayad e Schmidt,1997, p.38).<br />
Usando o benchmark é possível ter a real diferença do des<strong>em</strong>penho<br />
de cada tipo de impl<strong>em</strong>entação da interface Collection e ter a noção do impacto<br />
que cada escolha pode ocasionar no des<strong>em</strong>penho final do sist<strong>em</strong>a. A figura 13<br />
contém um ex<strong>em</strong>plo do uso do benchmark para realizar o teste, no caso o<br />
utilizado foi o Cronômetro já d<strong>em</strong>onstrado no capitulo 2 (figura 7) esse teste foi<br />
feito para medir o t<strong>em</strong>po decorrido ao adicionar itens a uma coleção, iterar<br />
sobre a coleção e r<strong>em</strong>over itens de uma coleção, e no caso se a interface<br />
passada como argumento do método for uma instancia de List o benchmark<br />
testa a velocidade de acesso á itens aleatórios.<br />
36
Figura 13: Benchmark para testar o des<strong>em</strong>penho<br />
de diversos tipos de coleções.<br />
Fonte: Elaborado pelo autor<br />
Realizando o teste com cinco impl<strong>em</strong>entações diferentes: ArrayList,<br />
LinkedList, Vector, TreeSet, HashSet os resultados obtidos por cada Classe<br />
foram os seguintes:<br />
Classe Iterar Adicionar R<strong>em</strong>over Random<br />
ArrayList 660 m/s 0 m/s 2360 m/s 0 m/s<br />
LinkedList 1100 m/s 50 m/s 0 m/s 26800 m/s<br />
Vector 880 m/s 0 m/s 2580 m/s 0 m/s<br />
TreeSet 1430 m/s 330 m/s 60 m/s Não é Lista<br />
HashSet 1430 m/s 110 m/s 50 m/s Não é Lista<br />
37
Com os resultados dos testes pode-se perceber o quanto ArrayList e<br />
o Vector por ser<strong>em</strong> estruturas matriciais s<strong>em</strong>elhantes possu<strong>em</strong> t<strong>em</strong>pos quase<br />
idênticos, sendo diferente somente que Vector possui uma sincronização<br />
padrão o que o faz ter des<strong>em</strong>penho um pouco mais lento. Se comparar<br />
ArrayList com LinkedList apesar de poder<strong>em</strong> executar as mesmas operações<br />
percebe-se resultados b<strong>em</strong> diferentes, onde um é mais rápido o outro e mais<br />
lento e vice versa. Onde obtiv<strong>em</strong>os resultado igual a zero significa que o t<strong>em</strong>po<br />
foi muito insignificante para o teste.<br />
Com isso comprova-se a importância de escolher a estrutura correta<br />
ao desenvolver-se um software.<br />
38
6 – Particularidades do <strong>Java</strong><br />
6.1. Garbage Collection<br />
Garbage Collection ou coleção de lixo é um processo usado para a<br />
automação do gerenciamento de m<strong>em</strong>ória. Com ele é possível recuperar uma<br />
área de m<strong>em</strong>ória inutilizada por um programa, o que pode evitar probl<strong>em</strong>as<br />
de vazamento de m<strong>em</strong>ória, resultando no esgotamento da m<strong>em</strong>ória livre para<br />
alocação. A sua grande vantag<strong>em</strong> é que o desenvolvedor não precisa ficar<br />
preocupado com desalocação de recursos, o próprio coletor de lixo faz uma<br />
varredura no programa e elimina os que não estão sendo usados, sobrando<br />
t<strong>em</strong>po para pensar <strong>em</strong> outros detalhes da impl<strong>em</strong>entação, outra grande<br />
vantag<strong>em</strong> é evitar erros humanos ao desalocar um recurso errado, que ainda<br />
estava sendo usado pelo programa, ou liberar uma região de m<strong>em</strong>ória mais de<br />
uma vez (JAVAFREE, 2009).<br />
O Garbage Collection é muito importante para um bom des<strong>em</strong>penho<br />
da aplicação, pois esta diretamente ligada ao custo de alocação e desalocação<br />
de m<strong>em</strong>ória. Se uma aplicação consome muita m<strong>em</strong>ória forçando assim o<br />
Sist<strong>em</strong>a Operacional a ter que usar a m<strong>em</strong>ória virtual ela consequent<strong>em</strong>ente<br />
terá uma perca de performance .<br />
Garbage Collector (coletor de lixo) é um sist<strong>em</strong>a de alocação<br />
automática de objetos na pilha, isso ocorre quando se inicia a JVM (<strong>Java</strong><br />
Virtual Machine), ele funciona como um contador, toda vez que um se faz uma<br />
referencia a um objeto ele anota, com isso ele sabe quantos referencias estão<br />
apontando para determinado espaço de m<strong>em</strong>ória, quando esse contador atinge<br />
zero o objeto vira um sério candidato a ser varrido da m<strong>em</strong>ória, então o<br />
39
Garbage Collector escolherá o momento certo para limpa-lo da pilha. Ele é<br />
nativo, ou seja, varia de JVM para JVM. No <strong>Java</strong> o desenvolvedor não t<strong>em</strong><br />
plenos poderes para mandar o Garbage Collector rodar na hora que ele<br />
desejar, o Máximo que ele pode fazer é tentar induzi-lo a rodar <strong>em</strong> determinada<br />
hora, o que não é garantia nenhuma que isso acontecerá (ROCHA, 2005a, p.46).<br />
Todo objeto possui um ciclo de vida que começa quando ele é criado<br />
(create), depois passa a ficar <strong>em</strong> uso (in use), torna-se invisível (invisible),<br />
depois inalcançável (Unreachable), coletado (collected), ele é finalizado<br />
(finalized) e por ultimo termina quando é desalocado (Deallocated).<br />
Quando um objeto é criado um espaço na m<strong>em</strong>ória é alocado para<br />
ele, a sua construção é então iniciada, o construtor da superclasse é chamado,<br />
no <strong>Java</strong> todas as classes herdam da classe pai Object, os iniciadores de<br />
instância e iniciadores de varáveis de instância são executados, então o resto<br />
do corpo do construtor é executado. A criação de um objeto gera custos de<br />
processamento, mas variam de JVM e de como a classe é impl<strong>em</strong>entada.<br />
Após o objeto ser criado e ser ligado a uma variável ele passa pra o estado de<br />
“uso”.<br />
O Garbage Collector começa a agir quando o objeto encontra-se no<br />
estado inalcançável, <strong>em</strong> outras palavras quando não existe nenhuma<br />
referência do tipo strong (forte), ou seja, pode ser alcançado por uma Thread<br />
que seja através de um objeto de referencia, quando ele chega nesse estado,<br />
passa a ser um candidato a ser coletado, apesar de estar pronto para ser<br />
coletado a JVM só o pode fazê-lo quando estiver precisando de espaço na<br />
pilha para alocar outros objetos, então o objeto passa para o estado de<br />
coletado e o garbage collector encaminha para o estado finalizado, quando um<br />
objeto é finalizado ele fica esperando a desalocação.<br />
Se o desenvolvedor quiser aumentar o t<strong>em</strong>po de vida de um objeto,<br />
ele terá que impl<strong>em</strong>entar um método finalizador, isso ocorre pelo fato de toda<br />
instancia da classe ter que chamar o método antes de desaloca-lo.<br />
40
Após o método ser finalizado o garbage collector trata de desaloca-<br />
lo e assim deixar a pilha com mais espaço, quando e como isso ocorre fica por<br />
conta da JVM.<br />
A máquina virtual da Sun utiliza a estratégia de coleta por gerações,<br />
essa estratégia classifica os objetos <strong>em</strong> vários grupos chamados de gerações,<br />
de acordo com sua idade, a coleta é realizada separadamente <strong>em</strong> cada<br />
geração e ocorre mais freqüent<strong>em</strong>ente nas gerações jovens, ou seja, no<br />
objetos novos, os objetos que sobreviv<strong>em</strong> a primeira coleta são promovidos<br />
para a próxima geração, as gerações representam áreas do HEAP a geração<br />
jov<strong>em</strong> é a área menor, onde é inicialmente alocada a m<strong>em</strong>ória para novos<br />
objetos. A geração antiga, ou estável, é uma área maior onde o espaço<br />
alocado não é para novos objetos, mas para acomodar objetos que sobreviv<strong>em</strong><br />
a uma ou mais coletas de lixo na área menor (ROCHA, 2005a, p25).<br />
Na versão 1.5 do <strong>Java</strong> foi inserido um novo recurso chamado de<br />
Ergonomia, ele t<strong>em</strong> como objetivo proporcionar um bom des<strong>em</strong>penho á JVM<br />
com um mínimo de linha de comando, ela tenta obter a melhor seleção do<br />
coletor de lixo, tamanho da pilha e compilador de t<strong>em</strong>po de execução (JIT- Just<br />
in time) (ORACLE, 2003).<br />
Seus ajustes são baseados <strong>em</strong> duas metas: pausa máxima e<br />
capacidade de processamento mínimo e t<strong>em</strong> como alvo aplicações que<br />
funcionam <strong>em</strong> grandes servidores, logo na instalação e na execução ela realiza<br />
os primeiros ajustes automáticos. Na instalação o sist<strong>em</strong>a tenta descobrir se<br />
esta numa maquina de classe Servidor ou Cliente, o parâmetro usado para<br />
avaliar se a maquina é cliente ou servidor é a m<strong>em</strong>ória física que no caso deve<br />
conter no mínimo dois gigas e se possui pelo menos duas CPU para o caso de<br />
servidor, se a maquina for servidora ele ira usar a Server JVM, se for cliente<br />
usara Client JVM (ROCHA, 2005b, p.63).<br />
Para configurar as metas de pausa máxima e de capacidade de<br />
processamento mínimo também conhecida como eficiência mínima, o<br />
41
desenvolvedor configura o uso mínimo e máximo da m<strong>em</strong>ória do HEAP (pilha),<br />
a partir daí o coletor efetua vários ajustes de parâmetros tais como o tamanho<br />
e proporcionalidade entre a geração jov<strong>em</strong>, espaços sobreviventes, geração<br />
estável e outros valores, como a alteração da política de promoção para<br />
geração estável, para conseguir bater essa meta, se o coletor não conseguir<br />
bater a meta o usuário pode ir ajustando ate conseguir uma configuração<br />
aceitável para sua aplicação. A ergonomia não trabalha com garantias, ou seja,<br />
ela não garante que as metas serão alcançadas, alguns comandos importantes<br />
para configurar a ergometria no coletor paralelo de alta eficiência são (ROCHA,<br />
2005b, p.65):<br />
• -XX:MaxGCPauseMillis=valor – configura a meta de pausas<br />
máximas, o valor indica a quantidade de t<strong>em</strong>po <strong>em</strong> milissegundos<br />
que máxima que o coletor poderá para a aplicação para realizar a<br />
coleta de lixo.<br />
• -XX:GCTimeRatio=n – define a meta de eficiência, n é um valor<br />
normalizado que mede a proporção de t<strong>em</strong>po dedicado á<br />
aplicação da forma 1:n, um ex<strong>em</strong>plo, se n for igual 15 o t<strong>em</strong>po<br />
dedicado a aplicação pela maquina virtual será 16(1+15) vezes<br />
mais t<strong>em</strong>po que a coleta de lixo.<br />
• -XX:+Use AdaptiveSizePolicy – é usado somente se a Server Jvm<br />
estiver com o coletor configurado default, essa opção faz com<br />
que a maquina virtual colete dados e baseia-se por eles para<br />
redimensionar as gerações jovens e antigas<br />
Para fazer-se uso da ergonomia é importante que não se defina um<br />
valor máximo para a pilha, e sim que se escolha uma meta de eficiência que<br />
seja suficiente para a aplicação, pois o sist<strong>em</strong>a aumentará a pilha ate atingir<br />
um valor que irá permitir que se alcance a meta de eficiência esperada.<br />
42
6.2. <strong>Java</strong> HotSpot Virtual Machine<br />
<strong>Java</strong> HotSpot Virtual Machine é a máquina virtual <strong>Java</strong><br />
impl<strong>em</strong>entada pela Sun Microsyst<strong>em</strong>s Inc’s. Ela fornece a base da plataforma<br />
<strong>Java</strong> e utiliza uma tecnologia de otimização dinâmica. Ela possui dois tipos de<br />
versões uma no lado cliente outra no lado servidor. A versão cliente minimiza<br />
t<strong>em</strong>po de início da aplicação e m<strong>em</strong>ória utilizada, enquanto que a versão para<br />
servidor maximiza velocidade de execução da aplicação (ROCHA, 2005b, p.5).<br />
As duas versões possu<strong>em</strong>:<br />
• Compilador adaptivo.<br />
• Alocação rápida de m<strong>em</strong>ória.<br />
• Liberação de m<strong>em</strong>ória automática.<br />
• Sincronização de threads escalável.<br />
A VM HotSpot possui diversas impl<strong>em</strong>entações de algoritmos para<br />
coleta de lixo baseados <strong>em</strong> gerações de objetos,a maioria deles utilizam uma<br />
das três estratégias de coleta <strong>em</strong> paralelo como serial, concorrente e<br />
incr<strong>em</strong>ental (ROCHA, 2005a, p.29).<br />
• Serial: ideal para sist<strong>em</strong>as monoprocessados. Trabalham <strong>em</strong><br />
série parando a aplicação para executar uma única Thread na<br />
CPU. Busca eficiência <strong>em</strong> detrimento de possíveis pausas<br />
longas.<br />
• Incr<strong>em</strong>entais: rodam <strong>em</strong> Threads de baixa prioridade,<br />
concorrendo com a aplicação s<strong>em</strong> interrompê-la.<br />
• Concorrente: executa <strong>em</strong> varias Threads <strong>em</strong> paralelo, buscando<br />
uma maior eficiência.<br />
A arquitetura da VM HotSpot é dividida <strong>em</strong> duas partes: t<strong>em</strong>po de<br />
execução (runtime) e o compilador (compiler). Na área de t<strong>em</strong>po de execução<br />
existe um interpretador de bytecodes, um gerenciador de m<strong>em</strong>ória, o coletor de<br />
lixo e o sincronizador de Threads. O Compilador trabalha com a tradução dos<br />
bytecodes para instruções nativas de maquina, melhorando assim a<br />
performance de execução (WILSON,2001, p.206).<br />
43
Figura 14 Arquitetura da maquina virtual<br />
Fonte: Wilson, 2001<br />
A máquina virtual permite que se tenha um controle sobre suas<br />
configurações, com o objetivo de manter s<strong>em</strong>pre um nível alto de seu<br />
des<strong>em</strong>penho, toda configuração e feita através de linhas de comando, todos<br />
eles começam com a escrita –x pod<strong>em</strong> ser obtidos através do comando de<br />
ajuda <strong>Java</strong> –x. Alguns comandos importantes são:<br />
• –Xnoclassgc: desabilita o coletor de lixo.<br />
• –Xms : define o tamanho inicial da pilha de objetos, o<br />
padrão e vir configurado com dois megabytes. Size é onde<br />
configura o novo tamanho, ao aumentá-lo pode-se melhorar o<br />
t<strong>em</strong>po de inicialização da aplicação.<br />
• –Xmx : define o tamanho Maximo da pilha de objetos, por<br />
padrão ele v<strong>em</strong> configurado com sessenta e quatro megabytes,<br />
se o programa precisar alocar mais m<strong>em</strong>ória que o configurado<br />
ele irá <strong>em</strong>itir a exceção OutOfM<strong>em</strong>oryError, o campo size é onde<br />
deve colocar o valor máximo para a pilha de objetos.<br />
• –Xprof: a máquina virtual habilita suas ferramentas de profiling.<br />
O ajuste correto da máquina virtual <strong>em</strong> grandes aplicações pode<br />
trazer ganhos bastante significativos <strong>em</strong> se tratando de des<strong>em</strong>penho. Um<br />
ajuste pode ser simplesmente a seleção da maquina virtual, se ela é servidora<br />
ou cliente, ou a definição manual de parâmetros de funcionamento.<br />
44
CONCLUSÃO<br />
Nesse trabalho foram apresentadas as definições de performance<br />
computacional, a importância da utilização da m<strong>em</strong>ória RAM e do t<strong>em</strong>po de<br />
inicialização de uma aplicação, as diferenças entre sist<strong>em</strong>as escaláveis e não<br />
escaláveis, o que é performance percebida pelo usuário e porque deve-se<br />
tentar melhora o t<strong>em</strong>po percebido, assim como boas práticas para medição de<br />
des<strong>em</strong>penho e como melhorá-lo com uso de estruturas de dados e algoritmos<br />
otimizados.<br />
È muito importante ao desenvolver um software levar <strong>em</strong> conta o<br />
des<strong>em</strong>penho final do ponto de vista do usuário. O que se vê <strong>em</strong> muitas<br />
<strong>em</strong>presas responsáveis pelo desenvolvimento de aplicações é a falta de<br />
conhecimento ou até de interesse de seus programadores <strong>em</strong> buscar uma<br />
melhoria do seu algoritmo ou da funcionalidade que esteja codificando no<br />
momento. Muitos deles não se atentaram que um t<strong>em</strong>po perdido na hora de<br />
planejar um software ou até mesmo uma funcionalidade <strong>em</strong> sua concepção<br />
pode trazer benefícios extraordinários quando o produto estiver concluído, além<br />
de evitar transtornos futuros quando o produto estiver sendo implantado no<br />
cliente.<br />
É preciso que desenvolvedores tenham conhecimento de como<br />
simples testes aplicados a seus códigos pod<strong>em</strong> descobrir furos enormes no<br />
desenvolvimento, e que essa prática deve-se tornar freqüente para se obter<br />
uma boa qualidade de seu sist<strong>em</strong>a. Para isso é essencial que se faça uso de<br />
técnicas como o benchmark, pois ele poderá identificar o quanto de t<strong>em</strong>po está<br />
sendo usado <strong>em</strong> determinada funcionalidade. Benchmarks são simples de<br />
impl<strong>em</strong>entar e oferec<strong>em</strong> uma enorme ajuda na medição de performance.<br />
45
Saber o comportamento <strong>em</strong> termos computacionais de algoritmos e<br />
estruturas de dados são de grande importância para qu<strong>em</strong> deseja criar um<br />
software robusto e com o mínimo de perdas de performance. O <strong>Java</strong> oferece<br />
algumas impl<strong>em</strong>entações próprias para algumas estruturas, cada uma<br />
recomendada para certo tipo de tarefa. Elas traz<strong>em</strong> melhorias consideráveis<br />
<strong>em</strong> termo de t<strong>em</strong>po computacional.<br />
Entender o funcionamento da maquina virtual e como configurá-la<br />
para obter um melhor des<strong>em</strong>penho pode fazer com que o software não corra<br />
riscos de um futuro estouro de m<strong>em</strong>ória, ou com que o mesmo perca t<strong>em</strong>po<br />
criando uma pilha de objetos muito maior do que a aplicação irá precisar. A<br />
JVM HotSpot contém diversos comandos que pod<strong>em</strong> ser usados para<br />
aperfeiçoar o seu funcionamento.<br />
Como trabalhos futuros pod<strong>em</strong>os sugerir a avaliação de ferramentas<br />
de profiling, com foco maior <strong>em</strong> suas funcionalidades e benefícios, assim como<br />
dissecar a maquina virtual HotSpot explicando os diferentes algoritmos que são<br />
usados no coletor de lixo, informando a vantag<strong>em</strong> de cada um deles e onde e<br />
como é <strong>em</strong>pregado pela VM.<br />
46
REFERÊNCIAS BIBLIOGRÁFICAS<br />
FAYAD, M. & SCHMIDT, C. D., Object-oriented application frameworks.<br />
ACM, 1997.<br />
HDIERKING. Understanding Perceived <strong>Performance</strong>. 2009. Disponível <strong>em</strong>:<br />
. Acessado <strong>em</strong> 16 de outubro de 2010.<br />
JAVAFREE. Garbage Collection. 2009. Disponível <strong>em</strong>: Acessado <strong>em</strong> 20 de nov<strong>em</strong>bro<br />
de 2010.<br />
LARMAN, C. Utilizando Uml e padrões 2ª edição, Bookman, 2003.<br />
LASKOWSKI, J. Reported issue with ZB300 labs and reading Tasks<br />
chapter in JRules 7 InfoCenter, 2010. Disponível <strong>em</strong>: Acessado <strong>em</strong> 25 de outubro de 2010.<br />
MANGAN, T. Perceived <strong>Performance</strong> -Tuning a Syst<strong>em</strong> for What Really<br />
Mattersng The <strong>Java</strong> HotSpot <strong>Performance</strong> Engine Architecture, 2008.<br />
Disponível <strong>em</strong>: Acessado<br />
<strong>em</strong> 27 de set<strong>em</strong>bro de 2010.<br />
MEYERS N. PerfAnal: A <strong>Performance</strong> Analysis Tool, 2000. Disponível <strong>em</strong> <<br />
http://java.sun.com/developer/technicalArticles/Programming/perfanal/ >.<br />
Acessado <strong>em</strong> 25 de outubro de 2010.<br />
47
MOREIRA E., Sist<strong>em</strong>as Distribuídos – introdução, 2009 Disponível <strong>em</strong> <<br />
http://erikomoreira.com.br/flf/sd/slides/introducao.6s.pdf>. Acessado <strong>em</strong> 20 de<br />
set<strong>em</strong>bro de 2010.<br />
O’HAIR K., HPROF: A Heap/CPU Profiling Tool in J2SE 5.0, 2004<br />
Disponível <strong>em</strong> . Acessado <strong>em</strong> 29 de<br />
set<strong>em</strong>bro de 2010.<br />
ORACLE, JRockit JV - Diagnostics Guid, 2009 Disponível <strong>em</strong>:<br />
Acessado<br />
<strong>em</strong> 26 de outubro de 2010.<br />
__________. Tuning Garbage Collection with the 5.0 <strong>Java</strong> Virtual<br />
Machine. 2003. Disponível <strong>em</strong>: < http://www.oracle.com/technetwork/java/gc-<br />
tuning-5-138395.html> Acessado <strong>em</strong> 26 de nov<strong>em</strong>bro de 2010.<br />
__________. Tuning The <strong>Java</strong> HotSpot <strong>Performance</strong> Engine Architecture.<br />
2010. Disponível <strong>em</strong>: <br />
Acessado <strong>em</strong> 27 de nov<strong>em</strong>bro de 2010.<br />
ROCHA, H. Gerência de m<strong>em</strong>ória <strong>em</strong> <strong>Java</strong>, 2005a , Disponível <strong>em</strong>: <br />
Acessado <strong>em</strong> 26 de nov<strong>em</strong>bro de 2010.<br />
__________. Gerência de m<strong>em</strong>ória <strong>em</strong> <strong>Java</strong> parte 2: Monitoração e<br />
configuração da maquina virtual HotSpot, 2005b , Disponível <strong>em</strong>:<<br />
http://www.argonavis.com.br/cursos/java/j100/java-5-m<strong>em</strong>-2.pdf> Acessado <strong>em</strong><br />
26 de nov<strong>em</strong>bro de 2010.<br />
TMURGENT. Perceived <strong>Performance</strong>, 2003. Disponível <strong>em</strong>:<br />
. Acessado<br />
<strong>em</strong> 20 de set<strong>em</strong>bro de 2010.<br />
48
WILSON, S. <strong>Performance</strong>, 2001 Disponível <strong>em</strong> < http://java.sun.com/<br />
docs/books/performance/1st_edition/html/JP<strong>Performance</strong>.fm.html#16387 >.<br />
Acessado <strong>em</strong> 20 de set<strong>em</strong>bro de 2010.<br />
49