17.01.2013 Views

Entendendo a Performance em Aplicações Java - FLF

Entendendo a Performance em Aplicações Java - FLF

Entendendo a Performance em Aplicações Java - FLF

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!