FACULDADE BOA VIAGEM
Carlos Eduardo Arruda Chaves
ANÁLISE COMPARATIVA DO CONSUMO DE MEMÓRIA E TEMPO DE
EXECUÇÃO NA PLATAFORMA ANDROID: UM ESTUDO DE CASO
Recife
2014
Carlos Eduardo Arruda Chaves
ANÁLISE COMPARATIVA DO CONSUMO DE MEMÓRIA E TEMPO DE
EXECUÇÃO NA PLATAFORMA ANDROID: UM ESTUDO DE CASO
Monografia apresentada como requisito
para conclusão do Curso de Ciência da
Computação da Faculdade Boa Viagem
(FBV).
Orientador: Felipe Silva Ferraz
Recife
2014
Catalogação na fonte Biblioteca da Faculdade Boa Viagem, Recife/PE
C111a Chaves,
Carlos Eduardo Arruda.
Análise comparativa do consumo de memória e tempo de execução
na plataforma android: um estudo de caso / Carlos Eduardo Arruda
Chaves. -- Recife : FBV | Devry, 2014.
65 f. : il.
Orientador(a) : Felipe Silva Ferraz.
Trabalho de Conclusão de Curso (Computação) -- Faculdade Boa
Viagem | Devry.
Inclui apêndice.
1. Dispositivos Móveis. 2. Android. 3. Java. I. Título.
CDU 004[14.1]
Ficha catalográfica elaborada pelo bibliotecário: Jadinilson Afonso CRB-4/1367
Carlos Eduardo Arruda Chaves
ANÁLISE COMPARATIVA DO CONSUMO DE MEMÓRIA E TEMPO DE
EXECUÇÃO NA PLATAFORMA ANDROID: UM ESTUDO DE CASO
Monografia apresentada como pré-requisito para conclusão do Curso de Ciência
da Computação da Faculdade Boa Viagem (FBV).
Aprovada em:
Recife, 18 de junho de 2014
Banca Examinadora
_________________________________________________________
Felipe Silva Ferraz (Orientador)
(Mestre em Ciências da Computação, Universidade Federal de Pernambuco)
________________________________________________________
Maria Carolina da Silva (1o Examinador)
(Mestre em Ciências da Computação, Universidade Federal de Pernambuco)
_______________________________________________________
Filipe Carlos Albuquerque Calegario (2 o Examinador)
(Mestre em Ciências da Computação, Universidade Federal de Pernambuco)
Dedico a Deus, a todas as pessoas que
contribuíram diretamente ou indiretamente
durante a minha formação acadêmica, a
toda minha família e principalmente aos
meus pais, por terem acreditado em mim,
fornecendo todo o carinho e a melhor
educação possível, e por serem exemplos
de boas pessoas.
Em especial, dedico a Isis Vilaça, que é
uma pessoa muito especial em minha vida
e que sempre esteve ao meu lado me
apoiando em todos os momentos.
AGRADECIMENTOS
Agradeço primeiramente aos meus pais e à minha família por terem acreditado
em mim, fornecendo todo carinho e apoio necessário para que eu chegasse até
aqui. Em segundo lugar, agradeço a todos os professores que fizeram parte da
minha formação acadêmica, em especial Antônio Luiz Cavalcanti, Danilo Araújo,
Euclides Arcoverde, Felipe Ferraz, João Marcelo, Marconi Souza, Paulo Pereira,
Renata Freire, Tayanna Sotero, Tse Min Lin e Walter Galão, pois sem eles não
teria o conhecimento que possuo hoje. Agradeço também meus amigos de
graduação Célio Alves e Amélia Pessoa que estiveram ao meu lado durante esta
longa caminhada. Por fim, mas não com menor mérito, agradeço à minha
namorada Isis Vilaça que sempre me apoiou e superou todos os estresses
vivenciados durante o curso de Ciências da Computação, principalmente nas
semanas de provas e de entregas de projetos.
“Science never solves a problem
without creating ten more.”
(George Bernard Shaw)
RESUMO
Os smartphones estão tornando-se cada vez mais presentes no dia a dia das
pessoas. Em 2013, a venda destes aparelhos superou a de celulares tradicionais
e os dispositivos mais vendidos foram aqueles de menor custo. Os melhores
smartphones que estão sendo comercializados, ainda possuem uma quantidade
limitada de memória RAM. Com isso, esse trabalho tem o objetivo de comparar
algumas técnicas de programação já existentes da linguagem Java, identificar
quais podem auxiliar na economia de memória RAM e quais podem ser
executadas no menor período de tempo na plataforma de desenvolvimento
Android.
Palavras-chave: dispositivos móveis, Android, Java, smartphone, memória RAM,
tempo de execução, memória heap, técnicas de programação, vazamento de
memória.
ABSTRACT
The smartphones are becoming increasingly present in the daily life of people. In
2013, the sale of these devices surpassed traditional mobile phones and more
devices sold were those of lower cost. The best smartphones being sold still have
a limited amount of RAM. With this, this work have the objective to compare some
existing techniques of the Java programming language, and identify which could
help RAM economy and which can be performed in the shortest period of time in
the Android development platform.
Keywords: mobile devices, Android, Java, Smartphone, memory RAM, execution
time, heap memory, programming techniques, memory leak.
LISTA DE ILUSTRAÇÕES
Figura 1 - Vendas de telefone celular e smartphone no Brasil ......................... 13
Figura 2 - Quantitativo de vendas de smartphones em 2013 no mundo .......... 14
Figura 3 - Declaração de uma String................................................................ 18
Figura 4 - Utilização do operador de concatenação ......................................... 18
Figura 5 - Declaração de StringBuilder ............................................................ 19
Figura 6 - Utilização do método append ........................................................... 19
Figura 7 - Utilização do método insert .............................................................. 19
Figura 8 - Declaração de variável em Java ...................................................... 20
Figura 9 - Algumas implementações da interface List ...................................... 21
Figura 10 – Utilização de List ........................................................................... 21
Figura 11 - Herdando a classe Thread ............................................................. 23
Figura 12 - Diagrama de estado do ciclo de vida de uma thread ..................... 24
Figura 13 - Anatomia de um Integer ................................................................. 25
Figura 14 - Diagrama que representa a arquitetura Android ............................ 27
Figura 15 - Componentes de uma aplicação Android ...................................... 28
Figura 16 - Eclipse MAT ................................................................................... 31
Figura 17 – Configuração da máquina de desenvolvimento e coleta de dados 33
Figura 18 - Configurações do emulador Android .............................................. 34
Figura 19 - Tempo de execução das classes String e StringBuilder ................ 38
Figura 20 - Consumo de memória das classes String e StringBuilder ............. 38
Figura 21 - Tempo de execução dos tipos primitivos adequados e inadequados
......................................................................................................................... 42
Figura 22 - Consumo de memória dos tipos primitivos adequados e inadequados
......................................................................................................................... 42
Figura 23 - Tempo de execução do procedimento utilizando ArrayList e
LinkedList ......................................................................................................... 46
Figura 24 – Consumo de memória do procedimento utilizando ArrayList e
LinkedList ......................................................................................................... 46
Figura 25 - Tempo de execução do procedimento utilizando int e Integer ....... 49
Figura 26 – Consumo de memória do procedimento utilizando int e Integer ... 49
Figura 27 - Tempo de execução do procedimento utilizando long e Long ....... 51
Figura 28 - Consumo de memória do procedimento utilizando long e Long .... 51
Figura 29 - Consumo de memória do procedimento utilizando threads ........... 56
Figura 30 – Quantidade de threads executadas paralelamente ....................... 56
Figura 31 - Utilizando uma classe de thread privada e estática que estende a
classe Thread com política de cancelamento................................................... 64
Figura 32 – Utilizando uma classe de thread anônima..................................... 65
Figura 33 - Utilizando uma classe de thread privada e estática que estende a
classe Thread ................................................................................................... 65
LISTA DE TABELAS
Tabela 1 – Resumo das configurações dos principais aparelhos..................... 15
Tabela 2 - Tipos primitivos em Java ................................................................. 20
Tabela 3 - Wrappers de tipo primitivo ............................................................... 24
Tabela 4 – Resultado da execução do processamento com String.................. 36
Tabela 5 - Resultado da execução do processamento com StringBuilder ....... 37
Tabela 6 - Dados cadastrais de uma pessoa ................................................... 39
Tabela 7 - Atributos da classe PessoaSOK.java .............................................. 40
Tabela 8 - Atributos da classe PessoaNOK.java .............................................. 40
Tabela 9 – Resultado da execução utilizando os tipos de dados primitivos
adequadamente ............................................................................................... 41
Tabela 10 – Resultado da execução utilizando os tipos de dados primitivos
inadequadamente............................................................................................. 42
Tabela 11 – Resultado da execução utilizando LinkedList ............................... 44
Tabela 12 – Resultado da execução utilizando ArrayList ................................. 45
Tabela 13 – Resultado da execução utilizando o tipo primitivo int ................... 48
Tabela 14 – Resultado da execução utilizando a classe wrapper Integer ........ 49
Tabela 15 - Resultado da execução utilizando o tipo primitivo long ................. 50
Tabela 16 - Resultado da execução utilizando a classe wrapper Long ............ 51
Tabela 17 - Resultado da execução utilizando uma classe de thread anônima54
Tabela 18 - Resultado da execução utilizando uma classe de thread privada e
estática que estendia a classe Thread ............................................................. 55
Tabela 19 - Resultado da execução utilizando uma classe de thread privada e
estática que estendia a classe Thread com política de cancelamento ............. 56
LISTA DE ABREVIATURAS E SIGLAS
3D
Terceira Dimensão
ABINEE
Associação Brasileira da Industria Elétrica e Eletrônica
API
Interface de Programação de Aplicativos
GC
Garbage Colector
GB
GigaByte
DDR
Double Data Rate
EE
Enterprise Edition
HTC
High Tech Computer Corporation
IBM
International Business Machines
IDC
International Data Corporation
IDE
Ambiente de Desenvolvimento Integrado
JVM
Máquina Virtual Java
MB
MegaByte
LG
Lucky Goldstar
MAT
Memory Analyzer Tools
OHA
Open Handset Aliance
RAM
Memória de Acesso Aleatório
SO
Sistema Operacional
SSD
Disco de Estado Sólido
XML
Linguagem de Marcação Extensível
SUMÁRIO
1.
2.
INTRODUÇÃO .......................................................................................... 13
1.1
Descrição do problema ....................................................................... 15
1.2
Objetivo geral ...................................................................................... 15
1.3
Objetivos específicos .......................................................................... 16
REFERENCIAL TEÓRICO ....................................................................... 17
2.1
2.1.1.
String................................................................................................ 17
2.1.2.
StringBuilder .................................................................................... 18
2.2
Tipo de dados primitivos ..................................................................... 19
2.3
Listas ................................................................................................... 20
2.3.1.
LinkedList ......................................................................................... 22
2.3.2.
ArrayList ........................................................................................... 22
2.4
2.4.1.
Threads ............................................................................................... 22
Ciclo de vida de uma thread ............................................................ 23
2.5
Classes wrappers ................................................................................ 24
2.6
Open Handset Aliance (OHA) ............................................................. 25
2.7
Android ................................................................................................ 26
2.7.1.
Arquitetura Android .......................................................................... 26
2.7.2.
Componentes de uma aplicação Android ........................................ 28
2.8
3.
String e StringBuilder .......................................................................... 17
Vazamento de memória (Memory Leak) ............................................. 29
METODOLOGIA ....................................................................................... 30
3.1
Tipo de pesquisa ................................................................................. 30
3.2
Instrumento de coleta de dados .......................................................... 30
3.3
Classificação dos dados...................................................................... 31
3.4
Cenário................................................................................................ 32
4.
ANÁLISE DE DADOS............................................................................... 35
4.1
4.1.1.
Cenário ............................................................................................ 35
4.1.2.
Resultado da avaliação .................................................................... 36
4.2
Utilização dos tipos de dados primitivos.............................................. 38
4.2.1.
Cenário ............................................................................................ 38
4.2.2.
Resultado da avaliação .................................................................... 40
4.3
Uso de Listas ...................................................................................... 43
4.3.1.
Cenário ............................................................................................ 43
4.3.2.
Resultado da avaliação .................................................................... 44
4.4
Utilização de tipos primitivos e classe wrappers ................................. 46
4.4.1.
Cenário ............................................................................................ 47
4.4.2.
Resultado da avaliação .................................................................... 47
4.4.2.1.
Uso de Integer e int ...................................................................... 48
4.4.2.2.
Uso de long e Long....................................................................... 50
4.5
5.
Uso das classes String e StringBuilder ............................................... 35
Uso de threads .................................................................................... 52
4.5.1.
Cenário ............................................................................................ 52
4.5.2.
Resultado da avaliação .................................................................... 53
CONCLUSÕES ......................................................................................... 58
REFERÊNCIAS ................................................................................................ 60
APÊNDICES .................................................................................................... 64
13
1. INTRODUÇÃO
O crescimento da classe média e o aumento do acesso ao crédito no Brasil
popularizou o uso de dispositivos móveis, tornando-os cada vez mais presentes
no dia a dia dos brasileiros.
Os dados presentes na Figura 1, foram coletados pela Associação
Brasileira da Industria Elétrica e Eletrônica (ABINEE) e International Data
Corporation (IDC) [1]. Eles correspondem aos resultados anuais de
comparações entre o uso de celulares tradicionais e smartphones ( são celulares
não só capazes de entrar na internet, mas que podem acessar lojas de aplicativos,
rodam um sistema operacional que possa executar funções mais complexas e tem
capacidade de processamento mais potente [2]) no Brasil.
Figura 1 - Vendas de telefone celular e smartphone no Brasil
70
60
58 67,1
Milhões
50
59,5
43,5
40
29,1 32
30
20
10
0
Celulares Tradicionais
Smartphones
Total
61,1
16
9,1
2011
2012
2013
58
9,1
67,1
43,5
16
59,5
29,1
32
61,1
Ano
Fonte: Adaptado de TELECO, 2014 [1]
É possível identificar que no ano de 2013 a venda de smartphones no
Brasil superou a de celulares tradicionais. Segundo Bruno Freitas [2], gerente de
pesquisas da IDC, a ultrapassagem ocorreu mais precisamente do mês de abril
para maio. Mundialmente foram vendidos 1,0096 bilhão de smartphones [3].
14
A Figura 2 mostra a quantidade de unidades vendidas em milhões de cada
sistema operacional (SO).
Figura 2 - Quantitativo de vendas de smartphones em 2013 no mundo
BlackBerry; 19,2;
2%
Windows Phone;
33,4; 3%
Outros; 10; 1%
iOS; 153,4; 15%
Android; 793,6;
79%
Fonte: Adaptado de IDC Worldwide Mobile Phone Tracker, Fevereiro, 2014 [3]
Pode-se verificar que os aparelhos com o SO Android foram os mais
vendidos de 2013, seguidos dos aparelhos com iOS (sistema operacional para
dispositivos móveis da Apple), Windows Phone (sistema operacional móvel da
Microsoft) e BlackBerry, respectivamente. Em complemento, 45,56% dos
dispositivos comprados custaram menos de 200 dólares [4].
Pesquisa realizada por Gareth Beavis [5] mostra os dez melhores
smartphones do mundo. A Tabela 1 lista os aparelhos e as principais
configurações de cada smartphone analisado.
15
Tabela 1 – Resumo das configurações dos principais aparelhos
Aparelho
Processador
Samsung Galaxy S4
Quad-core 1.9 GHz
Motorola Moto G
Quad-core 1.2 GHz
HTC One
Quad-core 1.7 GHz
Sony Xperia Z1 Compact
Quad-core 2.2 GHz
Google Nexus 5
Quad-core 2.26 GHz
LG G2
Quad-core 2.3 GHz
Samsung Galaxy S5
Quad-core 2.5 GHz
Sony Xperia Z2
Quad-core 2.3 GHz
HTC One M8
Quad-core 2.3 GHz
Média
Fonte: Autoria própria
Memória
RAM (GB)
2
1
2
2
2
2
2
3
2
2
Pode-se verificar que o smathphone que possui a maior quantidade de
Memória de Acesso Aleatório (RAM) é o Sony Xperia Z2 com 3 Gigabytes (GB).
O Motorola Moto G é o que possui a menor quantidade de memória física com
1GB, os demais parelhos possuem 2 GB. Dado este cenário, verifica-se que os
smartphones, mesmo os mais potentes ainda possuem um poder de
processamento limitado pela memória RAM.
1.1 Descrição do problema
Por mais que os dispositivos móveis estejam a cada dia mais desenvolvidos,
verifica-se que a memória RAM ainda é um recurso escasso. Conforme visto na
Tabela 1 a média de memória física existente entres os aparelhos é de 2,0 GB.
Sabendo desta limitação, evidencia-se a seguinte problemática: entre as
técnicas de programação já existentes, quais poderão minimizar o consumo de
memória RAM na plataforma Android?
1.2 Objetivo geral
O objetivo desta pesquisa é analisar as técnicas já existentes, na linguagem de
programação Java e identificar quais podem ser executadas com maior
velocidade e as que podem evitar o desperdício de memória RAM, utilizando
essa linguagem no desenvolvimento de aplicativos para a plataforma Android.
16
1.3 Objetivos específicos
Com o propósito de obter o objetivo geral estabelecido, este trabalho elucida
como objetivos específicos os itens abaixo:
•
Estudar o gerenciamento de memória da plataforma Android;
•
Desenvolver aplicativos Android, utilizando a linguagem de programação
Java;
•
Comparar práticas de programação e identificar quais podem evitar o
desperdício de memória e quais podem ser mais eficientes;
•
1
Analisar a memória heap1 dos aplicativos desenvolvidos.[6]
Heap: Local onde a Máquina Virtual Java (JVM) armazena todos os objetos criados pelo
aplicativo Java [6].
17
2. REFERENCIAL TEÓRICO
Este capítulo abordará os fundamentos teóricos, conceituando e exemplificando
cada técnica de programação analisada nesta pesquisa, foram elas: String,
StringBuilder, tipo de dados primitivos, ArrayList, LinkedList, classes wrappers e
threads. Também será explicado os principais componentes da plataforma
Android e o conceito de vazamento de memória.
2.1 String e StringBuilder
Nesta seção serão apresentados os conceitos teóricos e exemplos de utilização
das classes String e StringBuilder.
2.1.1. String
Segundo a Oracle [7], String é uma classe que faz parte do pacote java.lang e é
filha da classe Object que é a raiz da hierarquia de classes, toda as classes em
Java são filhas dela e todos os objetos, incluindo arrays implementam métodos
desta classe [8]. String Também implementa as interfaces Serializable,
CharSequence e Comparable. A Primeira interface permite que um objeto seja
serializado, ou seja, este objeto será transformado em um array de bytes e
poderá ser armazenado em disco ou transmitido por um stream [9]. A segunda
interface é uma sequência de caracteres, ela fornece acesso de apenas leitura
para muitos tipos diferentes de sequência de caracteres [10]. E a última interface
permite que um objeto seja comparado com outro objeto e, nesta comparação o
resultado poderá ser igual ou primeiro objeto maior ou segundo objeto maior [11].
Em Java, a classe String é caracterizada por um conjunto de caracteres,
seus valores são constantes e não podem ser modificados após sua
inicialização. Strings são imutáveis e, por esta razão, podem ser compartilhadas.
As representações de textos em programas Java são implementadas como
instâncias desta classe e sempre devem estar entre aspas duplas. A Figura 3
mostra um exemplo de uma String na linguagem de programação mencionada
anteriormente:
18
Figura 3 - Declaração de uma String
Fonte: Autoria própria
String fornece vários métodos nativos como uppercase, lowercase e
substring. O primeiro método converte todas as letras de uma String para
caracteres maiúsculos, o segundo converte todas as letras de uma String para
caracteres minúsculos e o ultimo retorna parte de uma String. Java fornece um
suporte especial para o operador de concatenação (+). A Figura 4 mostra um
exemplo de utilização do mesmo:
Figura 4 - Utilização do operador de concatenação
Fonte: Autoria própria
O valor contemplado na String resultado será “AB”.
2.1.2. StringBuilder
Segundo a Oracle [12], StringBuilder é uma classe que faz parte do pacote
java.lang, assim como String, é filha da classe Object e implementa as interfaces
Serializable e CharSequence. Diferente da classe String, StringBuilder
implementa a interface Appendable, esta permite que uma sequência de
caracteres seja adicionada em um objeto que implementa esta interface [13].
Em Java, StringBuilder caracteriza-se por uma sequência de caracteres e
seus valores podem ser modificados após sua inicialização. Por esta razão,
pode-se dizer que StringBuilder é mutável, mas sem garantia de sincronização.
A Figura 5 mostra um exemplo de uma StringBuilder na linguagem de
programação mencionada anteriormente:
19
Figura 5 - Declaração de StringBuilder
Fonte: Autoria própria
As principais operações desta classe são append e insert. O primeiro método
sempre adiciona os caracteres no final dos caracteres já existentes. O segundo
método insere os caracteres em um ponto especifico.
A Figura 6 mostra um exemplo de utilização do método append: se Z é uma
StringBuilder e contém o texto “java”, ao utilizar o método append(“se”), o
resultado de Z será “javase”.
Figura 6 - Utilização do método append
Fonte: Autoria própria
A Figura 7 mostra um exemplo de utilização do método insert:
Figura 7 - Utilização do método insert
Fonte: Autoria própria
Se Z é uma StringBuilder e contém o texto “java”, ao utilizar o método
insert(0, “se”), o resultado de Z será “sejava”.
2.2 Tipo de dados primitivos
Segundo Kathy Sierra [14] e a Oracle [15], os tipos de dados primitivos contém
valores básicos que incluem inteiros, booleanos e números de ponto flutuante.
Todas as declarações de variáveis em Java devem ter tipo e nome. A Figura
8 mostra como se declara uma variável nesta linguagem de programação, sendo
int o tipo da variável e número é o nome.
20
Figura 8 - Declaração de variável em Java
Fonte: Autoria própria
A Tabela 2 apresenta resumidamente os tipos de dados primitivos da
linguagem de programação Java.
Tabela 2 - Tipos primitivos em Java
Tipo
Quantidade
de bits
boolean
1
char
16
byte
short
8
16
Pode assumir os valores verdadeiro ou falso.
É uma implementação especifica da JVM.
Caractere em notação Unicode de 16bits.
Serve para armazenar dados alfa numéricos.
Número inteiro de oito bits.
Número inteiro de 16 bits
int
32
Número inteiro de 32 bits
long
64
float
32
Número inteiro de 64 bits
Representa números reais
simples.
double
64
Descrição
Valores
de
precisão
Representa números reais de precisão dupla.
Verdadeiro ou falso
0 a 65.535
-128 a 127
-32.768 a 32.767
- 2.147.483.648 a
2.147.483.647
-2^63 a 2^63 – 1
Possui 32 bits de
precisão.
Possui 64 bits de
precisão.
Fonte: Autoria própria
É possível verificar que cada tipo de dado possui tamanho e alcance
diferentes.
2.3 Listas
Segundo Caelum [16], lista é uma coleção que permite elementos duplicados e
mantém uma ordenação específica entre os elementos.
21
Figura 9 - Algumas implementações da interface List
Fonte: Adaptado de CAELUM [16]
A Figura 9 mostra que as classes LinkedList e ArrayList são
implementações da interface List.
Figura 10 – Utilização de List
Fonte: Autoria própria
A figura Figura 10 mostra um exemplo genérico de utilização de listas,
para instanciar uma LinkedList ou um ArrayList, basta trocar o texto
“Implementacao” pelo nome da implementação desejada. Após instanciar a
classe e utilizar o método add, os elementos 1 e 2 foram inseridos na lista.
22
2.3.1. LinkedList
Esta implementação faz parte do pacote java.util e, segundo a International
Business Machines (IBM) [17], é uma implementação da interface List. Permite
elementos duplicados, possui tamanho preciso e não necessita ser
redimensionada. A Figura 10 mostra um exemplo de utilização desta
implementação.
2.3.2. ArrayList
Esta implementação faz parte do pacote java.util e, segundo Ronaldo Lanhellas
[18], é a implementação da interface List mais utilizada. Esse tipo de lista é
dimensionado dinamicamente, ou seja, quando necessário o seu tamanho
aumenta em 50%. Isso significa dizer que se existir uma lista de tamanho 10 e
ela ficar cheia, seu tamanho aumentará para 15 automaticamente. A Figura 10
mostra um exemplo de utilização desta implementação.
2.4 Threads
Existem situações nas quais é preciso executar duas ou mais tarefas ao mesmo
tempo, como por exemplo, em um computador, escutar músicas e escrever um
documento. Em Java, quando o assunto é processamento paralelo fala-se de
Threads [19].
Segundo a Oracle [20], Thread é uma classe que faz parte do pacote
java.lang, filha da classe Object e implementa a interface Runnable. Uma
maneira de criar uma thread é herdando a classe Thread. A Figuras 11,
exemplifica essa maneira.
23
Figura 11 - Herdando a classe Thread
Fonte: Autoria própria
Segundo Caelum [21], ao estender a classe Thread, vários métodos são
herdados, porém apenas o método run é realmente utilizado.
2.4.1. Ciclo de vida de uma thread
Segundo Deitel [22], uma thread inicia o seu ciclo de vida no estado novo e
permanece neste estado até que o programa a inicie. Após isso, a thread estará
no estado executável, ou seja, executando sua tarefa.
Enquanto a thread está sendo executada, ela pode entrar no estado de
espera para aguardar que uma outra thread execute uma tarefa. A thread só
voltará ao estado executável quando for sinalizada que pode retomar sua
execução.
Uma thread no estado executável pode entrar no estado de espera
sincronizada por um intervalo específico de tempo. A thread retornará ao estado
executável quando o intervalo sincronizado expirar ou for notificado por outra
thread.
Uma thread entra no estado terminado quando completa sua tarefa. A Figura
12 ilustra os possíveis estados de uma thread.
24
Figura 12 - Diagrama de estado do ciclo de vida de uma thread
Fonte: DEITEL, 2005 [22]
2.5
Classes wrappers
Segundo Lanhellas [23], Java possui diversos wrappers que adicionam
funcionalidades a outras classes ou tipos primitivos. Um exemplo é o Integer,
que é a classe wrapper do tipo primitivo int. A Tabela 3 mostra os wrappers de
tipos primitivos.
Tabela 3 - Wrappers de tipo primitivo
Tipo primitivo
Classe wrapper
boolean
Boolean
char
Character
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
Fonte: Autoria própria
25
Segundo Bailey [17], a classe wrapper Integer tem uma sobrecarga adicional
de metadados2. A quantidade destes pode variar de acordo com a JVM, sendo
composta por:
a) Class: Um ponteiro para as informações sobre a classe, que descreve
o
tipo
de
objeto.
Neste
caso
é
um
ponteiro
para
a
classe java.lang.Integer.
b) Flags: Uma coleção de sinalizadores que descreve o estado do
objeto, incluindo o código hash para o objeto, se houver um, e a forma
do objeto (ou seja, se o objeto é um array ou não).
c) Lock: As informações de sincronização para o objeto — ou seja, se
o objeto está sincronizado atualmente.
Figura 13 - Anatomia de um Integer
Fonte: Adaptado de IBM, 2012 [17]
A Figura 13 mostra que um Integer utiliza 128 bits, sendo 32 bits utilizados
para armazenar o dado e 96 bits para metadados.
2.6
Open Handset Aliance (OHA)
Segundo Lecheta [24], a plataforma Android foi desenvolvida por um grupo de
empresas líderes em tecnologia móvel. O objetivo desta aliança era padronizar
uma plataforma de código aberto e livre para celulares, visando atender as
expectativas e tendências do mercado. Este grupo de empresas intitula-se OHA.
2 Metadados: São dados que descrevem dados. Eles provêm uma descrição concisa a respeito dos dados.
Os dados podem ser documentos, coleção de documentos, gráficos, tabelas, imagens, vídeos entre outros
tantos.[38]
26
“A Open Handset Alliance é um grupo formado por gigantes do mercado de
telefonia de celulares liderados pelo Google. Entre alguns integrantes do
grupo estão nomes consagrados como a HTC, LG, Motorola, Samsung,
Sony Ericsson, Toshiba,Sprint Nextel, China Mobile, T-Mobile, ASUS, Intel,
Garmin e muitas mais.[...]
Assim o objetivo do grupo é definir uma plataforma única e aberta para
celulares para deixar os consumidores mais satisfeitos com o produto final.
Outro objetivo principal dessa aliança é criar uma plataforma moderna e
flexível para o desenvolvimento de aplicações coorporativas. O resultado
dessa união, como pode ser visto, foi o nascimento do Android. [...]
Todos acabam se beneficiando dessa união: os fabricantes de celulares, os
usuários comuns e, é claro, os desenvolvedores de aplicações. LECHETA,
2010.
2.7 Android
Segundo Lecheta [24], a plataforma Android é livre e de código aberto. O sistema
operacional desta plataforma é baseado no kernel Linux 2.6 e possui uma
interface visual rica. É uma nova plataforma de desenvolvimento para aplicativos
móveis como smartphones e fornece um ambiente de desenvolvimento
poderoso, inovador e flexível. Para desenvolver aplicativos para esta plataforma
pode-se utilizar a linguagem de programação Java.
2.7.1. Arquitetura Android
De acordo com Lecheta [24], a arquitetura Android é flexível, pois você pode
integrar aplicações nativas com aplicações desenvolvida por você ou até mesmo
substituir qualquer aplicação nativa por uma que você mesmo criou.
Segundo Tosin [25], a arquitetura Android é composta por várias camadas
e componentes que serão explicadas posteriormente. A Figura 14 mostra um
diagrama que representa a arquitetura da plataforma Android.
27
Figura 14 - Diagrama que representa a arquitetura Android
Fonte: SOFTBLUE, 2011 [25]
a) Linux Kernel: É responsável por gerenciar memória, processos, threads
e a segurança dos arquivos e pastas, além de redes e drivers.
b) Libraries: Contempla as bibliotecas nativas escritas em C/C++ que fazem
parte da plataforma. Exemplos: APIs que estão nesta camada OpenGL
que é responsável pela renderização 3D, SQLite gerenciador de banco de
dados e o Midia Framework que fornece suporte a vários formatos de
áudio e vídeo.
c) Android Runtime: Fornece condições para que as aplicações baseadas
na plataforma sejam executadas.
d) Application Framework: Contempla as APIs Android que são utilizadas
pelas aplicações que executam sobre a plataforma.
e) Applications: Representa as aplicações que executam sobre a
plataforma. Estas podem ser nativas como gerenciador de contatos,
navegador, calendário ou aplicações criadas por terceiros. Esta é a
característica que garante um alto grau de flexibilidade e extensibilidade
da plataforma.
28
2.7.2. Componentes de uma aplicação Android
De acordo com Tosin [25], a plataforma Android disponibiliza um grupo de
componentes que possibilita o desenvolvimento de aplicativos para sua
plataforma. A Figura 15 ilustra esses componentes.
Figura 15 - Componentes de uma aplicação Android
Fonte: SOFTBLUE, 2011 [25]
a) Activities: São as representantes de telas da aplicação. Uma acitivity
geralmente possui view, que define como será feita a exibição visual para
os usuários. As activities são responsáveis por gerenciar os eventos da
tela e também coordenam o fluxo da aplicação.
b) Services: São processos que executam em segundo plano, ou seja, sem
que o usuário perceba e normalmente são utilizados para tarefas de longa
duração, como: sincronização de dados.
c) Content Providers: São provedores de conteúdo. É a maneira utilizada
para compartilhar dados entre as aplicações que estão sendo executadas
no diposistivo.
d) Broadcast Receivers: São componentes que ficam “ouvindo” a
ocorrência de determinados eventos, sendo que estes podem ser nativos
ou de outros aplicativos.
29
Junto
a
esses
componentes,
existe
o
arquivo
de
manifesto
AndroidManifest.xml. Ele é obrigatório a todos aplicativos Android e único para
cada aplicação. Neste arquivo são efetuadas as configurações gerais da
aplicação e dos componentes que fazem parte dela.
2.8 Vazamento de memória (Memory Leak)
Segundo Tosin [26], o vazamento de memória, termo comumente conhecido por
memory leak, não ocorre somente em C/C++, também acontece em Java. O
vazamento de memória pode ser de dois tipos:
a) Blocos de memória estão alocados e disponíveis para serem utilizados
pela aplicação, mas não estão acessíveis porque a aplicação não tem
nenhum ponteiro apontando para esta área de memória. Logo, esses
blocos de memória não podem ser utilizados nem pela aplicação e nem
por outros processos.
b) Blocos de memória possuem dados que poderiam ser liberados por serem
inacessíveis e que, por negligencia do programador ainda são
referenciados no código, mesmo sem estarem sendo utilizados,
impedindo de serem liberados.
Em Java o primeiro tipo não ocorre, pois o Garbage Collector (GC) é capaz
de detectar blocos de memória alocados e não referenciados e libera-los para
uso posterior.
O segundo tipo pode ocorrer nesta linguagem de programação, para isso
basta manter a referência de um ou mais objetos no código, mesmo sem utilizála depois. Desta forma o GC não poderá destruir os objetos, e eles continuarão
existindo na memória mesmo não sendo mais acessíveis. Quando os blocos de
memória disponibilizados para a aplicação acabarem a JVM lançará um erro do
tipo java.lang.OutOfMemoryError.
30
3. METODOLOGIA
Neste capítulo, serão esclarecidos os procedimentos metodológicos utilizados
para atingir o objetivo geral desta pesquisa, os quais envolverão a criação de
aplicativos Android e a análise do consumo de memória dos mesmos, tempo de
execução e número de threads.
3.1 Tipo de pesquisa
Este trabalho apresenta uma pesquisa de abordagem quantitativa com
procedimentos técnicos de estudo de caso e objetivo exploratório.
Segundo Freitas [27], pesquisa quantitativa é tudo pode ser quantificável,
o que significa traduzir em números, opiniões e informações para classificá-las
e analisá-las.
De acordo com Schramm [28], a essência do estudo de caso é tentar
esclarecer uma decisão, ou um conjunto de decisões, seus motivos,
implementações e resultados.
Segundo Gil [29], a pesquisa exploratória tem como objetivo principal o
aprimoramento de ideias ou descobertas de intuições.
3.2 Instrumento de coleta de dados
Para alcançar o objetivo desta pesquisa, a amostra foi investigada por meio da
observação sistemática e individual. De acordo com Gil [29], esta forma de coleta
de dados é realizada por um único indivíduo e tem como planejamento responder
aos propósitos preestabelecidos.
A coleta dos dados foi realizada com a ferramenta Eclipse Memory Analyzer
Tools (MAT) que analisa a heap do Java e contém recursos que ajudam a
encontrar vazamentos de memória e reduzir o consumo de memória [30]. A
Figura 16 mostra a tela inicial do Eclipse MAT. Nela podemos verificar o tamanho
da heap, a quantidade de classes e objetos bem como os objetos que consomem
mais memória.
31
Figura 16 - Eclipse MAT
Fonte: Autoria própria
3.3 Classificação dos dados
Para alcançar o objetivo desta pesquisa, analisou-se os dados obtidos pelo
instrumento de coleta de dados explicado na seção anterior. Os dados obtidos
foram consumo de memória, tempo de execução e número de threads.
a) Consumo de memória: Ao iniciar cada aplicativo e ao término de cada
procedimento foi feita uma cópia e análise da memória heap dos
aplicativos utilizando o Eclipse MAT.
32
b) Tempo de execução: O tempo de execução de cada procedimento foi
medido em segundos. Para coletar o tempo gasto em cada procedimento
foi coletada a hora de início e fim do mesmo. Após isso foi efetuada uma
subtração entre as horas coletadas para obter o tempo gasto em
segundos.
c) Número de threads: A cada thread iniciada um contador era
incrementado e a cada thread finalizada o contador era decrementado. Ao
termino do procedimento o número de threads que estavam sendo
executadas paralelamente era exibido.
3.4 Cenário
Nesta seção, serão descritas as configurações e softwares e hardware utilizados
para implementar os aplicados e coletar os dados dos mesmos.
Os softwares utilizados no desenvolvimento dos aplicativos e para fazer a
coleta dos dados estão descritos a seguir:
•
Eclipse Java Enterprise Edition (EE) IDE for Web Developers,
versão: Kepler Service Release 1;
•
Eclipse
Memory
Analyzer
-
API
feature,
versão:
Chart
feature,
versão:
1.3.1.201401071412;
•
Eclipse
Memory
Analyzer
-
1.3.1.201401071412;
•
Android Development Toolkit, versão 22.2.1.v201309180102833290.
As configurações da máquina utilizada para o desenvolvimento dos
aplicativos e para realizar a coleta de dados estão descritas a seguir:
• Modelo: Samsung 530U3C-AD5BR [31];
• Processador: Intel® Core™ i7 3517U (1.90 GHz, 4 MB L3 Cache);
• Memoria: 8 GB DDR3;
• Disco rígido: 500 GB S-ATA + 24 GB iSSD Express Cache;
• Sistema Operacional: Ubuntu 13.04.
A Figura 17 mostra as configurações da máquina e o sistema operacional
utilizado durante essa pesquisa.
33
Figura 17 – Configuração da máquina de desenvolvimento e coleta de dados
Fonte: Autoria própria
Para efetuar a coleta de dados, foi utilizado um emulador Android com as
características descritas a seguir:
• Dispositivo: 2.7” QVGA (240 X 320: ldpi);
• Versão Android: 4.3 Jelly Bean – Level da API 18;
• Memória RAM: 512 MB;
• Tamanho da heap 16 MB;
• Processador cortex-a8;
• Memória interna: 200 MB;
• Cartão de memória: 200 MB.
A Figura 18 mostra as configurações do emulador Android utilizado
durante a coleta dos dados.
34
Figura 18 - Configurações do emulador Android
Fonte: Autoria própria
35
4. ANÁLISE DE DADOS
Neste capítulo, serão apresentados os resultados obtidos a partir da realização
desta pesquisa no emulador Android, cujas características foram expostas no
capítulo 3. Para isso, foram coletadas as cópias da memória heap dos aplicativos
antes e depois da execução, bem como o tempo de execução de cada
procedimento. Os dados foram coletados e organizados em gráficos e tabelas,
de maneira a possibilitar a análise e comparação entre as técnicas de
programação analisadas.
4.1 Uso das classes String e StringBuilder
Nesta sessão será analisado o uso das classes String e StringBuilder, estudos
[32] [33] exibem que ao utilizar a classe StringBuilder é possível evitar o trashing
(situação na qual é utilizando uma grande quantidade de recurso para fazer um
trabalho mínimo) de memória e obter ganhos de performance. A primeira classe
é caracterizada por uma sequência de caracteres, cujos valores não podem ser
alterados após sua inicialização. A segunda classe assim como String é
caracterizada por um conjunto de caracteres, porem pode ser modificada após
sua criação.
4.1.1. Cenário
Para realizar as medições, foi desenvolvido um aplicativo Android que continha
pacotes,
AndroidManifest.xml,
MainActivity.java,
StringActivity.java,
StringbuilderActivity.java e activity_main.xml, sendo detalhados a seguir:
• AndroidManifest.xml: Contemplava as declarações das três activities;
• MainActivity.java: Principal activity com dois botões (String e
StringBuilder). O primeiro botão inicia a “StringActivity.java”, já o
segundo inicializa a “StringbuilderActivity.java”;
• StringActivity.java: Possui uma repetição que concatena todos os
números de 0 (zero) à 4999 (quatro mil novecentos e noventa e nove)
em uma String utilizando o operador (+);
36
• StringbuilderActivity.java: Contém uma iteração que encadeia todos os
números de 0 (zero) à 4999 (quatro mil novecentos e noventa e nove)
em uma StringBuilder utilizando o operador append;
• activity_main.xml: Arquivo de layout que possui um LinearLayout com
orientação vertical e dois botões.
4.1.2. Resultado da avaliação
Para esse cenário, a MainActivity.java foi executada no emulador e, ao concluir
seu carregamento, o botão com o texto “String” foi pressionado.
Este procedimento efetua a medição da memória heap antes e depois da
execução do laço mencionado anteriormente. Para a primeira execução, o
resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,0 MB de
memória após realização do mesmo.
Esse procedimento foi executado mais quatro vezes e os resultados obtidos
estão listados na Tabela 4.
Tabela 4 – Resultado da execução do processamento com String
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
(%)
Tempo de
execução (s)
1
1,9
2,0
5,26
11,128
2
1,9
2,0
5,26
11,774
3
1,9
2,0
5,26
11,024
4
1,9
2,0
5,26
11,722
5
1,9
2,0
5,26
10,859
Conclusão
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo de memória de
5,26% em média. Desta forma, pode-se concluir que após pressionar o botão
com o texto “String” houve um acréscimo no consumo da heap. Em
complemento, pode-se verificar que o tempo de execução foi de 11,301
segundos em média.
37
Depois desta execução, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “Stringbuilder”. Este procedimento da mesma
forma que o anterior, realiza a medição da memória heap antes e depois da
execução do laço. Na primeira execução, o resultado obtido foi 1,9 MB de
memória antes da execução do laço e 2,0 MB de memória após realização do
mesmo.
Esse procedimento, foi executado mais 4 vezes e os resultados obtidos
estão listados na Tabela 5.
Tabela 5 - Resultado da execução do processamento com StringBuilder
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,0
5,26
0,159
2
1,9
2,0
5,26
0,142
3
1,9
2,0
5,26
0,174
4
1,9
2,0
5,26
0,150
5
1,9
2,0
5,26
0,154
Conclusão
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Aumento do consumo de
memória RAM em 5,26%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de 5,26%
em média. Desta forma, pode se concluir que após pressionar o botão com o
texto “Stringbuilder” houve um acréscimo no consumo da heap. Em adição,
pode-se verificar que o tempo de execução foi de 0,156 segundos em média.
As Figuras 19 e 20 mostram o tempo de execução e o consumo de memória
após a execução do procedimento, respectivamente.
38
Figura 19 - Tempo de execução das classes
String e StringBuilder
Figura 20 - Consumo de memória das
classes String e StringBuilder
11,301
12,000
2,0
2,0
2,0
8,000
MB
Segundos
10,000
6,000
1,0
4,000
2,000
0,156
0,000
0,0
Tempo de execução
String
Consumo de memória
StringBuilder
String
Fonte: Autoria própria
StringBuilder
Fonte: Autoria própria
É possível identificar que o consumo de memória foi semelhante. Em
contrapartida, o tempo de execução da classe StringBuilder foi, em média,
98,62% mais rápida que a sua concorrente, a classe String.
4.2 Utilização dos tipos de dados primitivos
Nesta seção será abordado o uso dos tipos de dados primitivos em Java que
podem ser byte, short, int, long, float, double, boolean ou char. Esta linguagem
de programação é fortemente tipada, ou seja, em todas as declarações de
variáveis deve-se informar o tipo de dados da mesma.
De acordo com Marcio Junior [34], os tipos primitivos determinam o tipo e o
tamanho da informação que será armazenada em uma variável. Utilizando os
tipos de dados primitivos de maneira correta pode-se evitar o desperdício de
memória. Diante disto, será efetuada uma análise focada em quantificar este
desperdício.
4.2.1. Cenário
Para realizar as medições, foi construído um aplicativo Android que continha
pacotes,
AndroidManifest.xml,
InicioActivity.java,
InadequadoActivity.java,
39
AdequadoActivity.java, PessoaNOK.java, PessoaSOK.java e activity_main.xml,
sendo detalhados a seguir:
• AndroidManifest.xml: Contempla as declarações das três activities;
• InicioActivity.java: Principal activity com dois botões (Adequado e
Inadequado). O primeiro botão inicia a “AdequadoActivity.java” já o
segundo inicializa a “InadequadoActivity.java”;
• AdequadoActivity.java: Possuía uma repetição de 0 (zero) à 9999 (nove
mil novecentos e noventa e nove) para cada iteração, foi adicionada
uma pessoa, que foi representada pela classe PessoaSOK da Tabela
7, em uma lista. Os dados cadastrais de cada pessoa estão na Tabela
6. No final do processo, a lista contemplou 10000 (dez mil) pessoas
cadastradas;
• InadequadoActivity.java: Possuía uma repetição de 0 (zero) à 9999
(nove mil novecentos e noventa e nove) em cada iteração, foi
adicionada uma pessoa, que foi representada pela classe PessoaNOK
da Tabela 8, em uma lista. Os dados cadastrais de cada pessoa estão
na Tabela 6. No final do processo a lista contemplou 10000 (dez mil)
pessoas cadastradas;
Tabela 6 - Dados cadastrais de uma pessoa
Nome atributo
Valor
Idade
20
Sexo
M
identidade
9999999
cpf
99999999999
Fonte: Autoria própria
• PessoaSOK.java: classe que representava uma pessoa no mundo
orientado a objetos. A definição dos tipos de dados e o nome dos
atributos estão definidos na Tabela 7;
40
Tabela 7 - Atributos da classe PessoaSOK.java
Tipo de dados
Nome do
atributo
byte
idade
char
sexo
int
identidade
long
cpf
Fonte: Autoria própria
• PessoaNOK.java: Classe que representava uma pessoa no mundo
orientado a objetos. Diferente da classe PessoaSOK.java os atributos
idade e identidade são dos tipos de dados int e long, respectivamente.
Não existe a necessidade do primeiro atributo ser um int, pois a idade
de uma pessoa pode ser representada por um byte. Já a segundo
atributo pode ser representado por um int. A definição dos tipos de
dados e o nome dos atributos estão definidos na Tabela 8;
Tabela 8 - Atributos da classe PessoaNOK.java
Tipo de dado
Nome do
atributo
int
idade
char
sexo
long
identidade
long
cpf
Fonte: Autoria própria
•
activity_main.xml: Arquivo de layout que possui um LinearLayout
com orientação vertical e dois botões.
4.2.2. Resultado da avaliação
Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir
seu carregamento, o botão com o texto “Adequado” foi pressionado.
Este procedimento efetuou a medição da memória heap antes e depois da
execução do laço mencionado anteriormente. Para a primeira execução, o
resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,2 MB
memória após a realização do mesmo.
41
Esse procedimento foi executado mais quatro vezes e os resultados obtidos
estão listados na Tabela 9.
Tabela 9 – Resultado da execução utilizando os tipos de dados primitivos adequadamente
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,2
15,79
1,630
2
1,9
2,2
15,79
1,790
3
1,9
2,2
15,79
1,726
4
1,9
2,2
15,79
1,602
5
1,9
2,2
15,79
1,581
Conclusão
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo de memória de, em
média, 15,79%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “Adequado”, houve um acréscimo no consumo da heap. Em adição,
pode-se verificar que o tempo de execução foi, em média, 1,666 segundos.
Depois desta execução, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “Inadequado”. Este procedimento, da mesma
forma que o anterior, realizou a medição da memória heap antes e depois da
execução do laço. Na primeira execução, o resultado obtido foi 1,9 MB de
memória antes da execução do laço e 2,3 MB de memória após realização do
mesmo.
Esse procedimento foi executado mais 4 vezes e os resultados obtidos estão
listados na Tabela 10.
42
Tabela 10 – Resultado da execução utilizando os tipos de dados primitivos inadequadamente
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,3
21,05
1,447
2
1,9
2,3
21,05
1,515
3
1,9
2,3
21,05
1,583
4
1,9
2,3
21,05
1,437
5
1,9
2,3
21,05
1,500
Conclusão
Aumento do consumo
memória de 21,05%.
Aumento do consumo
memória de 21,05%.
Aumento do consumo
memória de 21,05%.
Aumento do consumo
memória de 21,05%.
Aumento do consumo
memória de 21,05%.
de
de
de
de
de
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo de memória de, em
média, 21,05%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “Inadequado”, houve um acréscimo no consumo da heap. Em adição,
pode-se verificar que o tempo de execução foi, em média, 1,496 segundos.
As Figuras 21 e 22 mostram o tempo de execução e o consumo de memória
após a execução do procedimento, respectivamente.
Figura 21 - Tempo de execução dos tipos
primitivos adequados e inadequados
Figura 22 - Consumo de memória dos tipos
primitivos adequados e inadequados
2,000
2,5
1,666
2,3
2,0
1,5
MB
Segundos
1,496
2,2
1,000
1,0
0,5
0,000
0,0
Tempo de execução
Adequado
Inadequado
Fonte: Autoria própria
Consumo de memória
Adequado
Inadequado
Fonte: Autoria própria
É possível identificar que o consumo de memória do uso adequado dos tipos
primitivos foi, em média, 4,35% inferior ao dos tipos de dados inadequados. Em
43
contrapartida, o tempo de execução da primeira implementação foi, em média,
11,36% superior a segunda forma.
4.3 Uso de Listas
Nesta seção será abordado o uso das classes LinkedList e ArrayList, pois
estudos [17] [35] mostram que o desempenho dessas implementações são
diferentes dependendo da operação utilizada, porém não medem a quantidade
de memória RAM que pode ser economizada.
Ambas são implementações da interface List, permitem entradas duplicadas
e seus elementos podem ser acessados por meio de índice (posição da lista). A
primeira
classe
redimensionada.
possui
tamanho
preciso,
Já
segunda
implementação
a
ou
seja,
não
não
é
precisa
ser
precisamente
redimensionada e o tamanho por entrada do ArrayList é menor do que no
LikendList.
4.3.1. Cenário
Para realizar as medições, foi implementado um aplicativo Android que continha
pacotes,
AndroidManifest.xml,
ArrayListActivity2.java,
InicioActivity.java,
LinkedListActivity.java
e
ArrayListActivity1.java,
activity_main.xml,
sendo
detalhados a seguir:
• AndroidManifest.xml: Contemplava a declaração de três activities;
• InicioActivity.java: Principal activity com dois botões (LinkedList e
ArrayList1). O primeiro botão iniciava a “LinkedListActivity.java” e o
segundo inicializava a “ArrayList1Activity.java”;
• LinkedListActvity.java: Possuía uma repetição que adicionava todos os
números de 0 (zero) à 49999 (quarenta e nove mil novecentos e
noventa e nove) em uma LinkedList utilizando o método (add);
• ArrayList1Activity.java: Continha uma iteração que acrescentava todos
os números de 0 (zero) à 49999 (quarenta e nove mil novecentos e
noventa e nove) em um ArrayList utilizando o método (add);
44
• activity_main.xml: Arquivo de layout que possuía um LinearLayout com
orientação vertical e dois botões.
4.3.2. Resultado da avaliação
Para esse cenário, a InicoActivity.java foi inicializada no emulador e, ao concluir
seu carregamento, o botão com o texto “LinkedList” foi pressionado.
Este procedimento, efetuou a medição da memória heap antes e depois da
execução do laço mencionado anteriormente. Para a primeira execução, o
resultado obtido foi 1,9 MB de memória antes da execução do laço e 3,8 MB de
memória após realização do mesmo.
Esse procedimento foi executado mais quatro vezes e os resultados obtidos
estão listados na Tabela 11:
Tabela 11 – Resultado da execução utilizando LinkedList
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
3,8
100
6,137
2
1,9
3,8
100
6,268
3
1,9
3,8
100
6,127
4
1,9
3,8
100
6,159
5
1,9
3,8
100
6,093
Conclusão
Aumento do consumo de
memória RAM em 100%.
Aumento do consumo de
memória RAM em 100%.
Aumento do consumo de
memória RAM em 100%.
Aumento do consumo de
memória RAM em 100%.
Aumento do consumo de
memória RAM em 100%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 100%. Desta forma, pode-se concluir que após executar o procedimento
citado anteriormente houve um acréscimo no consumo da heap. Em adição,
pode-se verificar que o tempo de execução ficou em média de 6,157 segundos.
Depois desta execução, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “ArrayList1”. Este procedimento da mesma
forma que o anterior, realizou a medição da memória heap antes e depois da
execução do laço. Na primeira execução o resultado obtido foi 1.9 MB de
45
memória antes da execução do laço e 2.9 MB de memória após realização do
mesmo.
Esse procedimento, foi executado mais 4 vezes e os resultados obtidos
estão listados na Tabela 12.
Tabela 12 – Resultado da execução utilizando ArrayList
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,9
52,63
3,294
2
1,9
2,9
52,63
3,134
3
1,9
2,9
52,63
3,479
4
1,9
2,9
52,63
3,228
5
1,9
2,9
52,63
3,440
Conclusão
Aumento do consumo
memória em 52,63%.
Aumento do consumo
memória em 52,63%.
Aumento do consumo
memória em 52,63%.
Aumento do consumo
memória em 52,63%.
Aumento do consumo
memória em 52,63%.
de
de
de
de
de
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 52,63%. Desta forma, pode-se concluir que após executar o
procedimento citado anteriormente houve um acréscimo no consumo da heap.
Em adição, pode-se verificar que o tempo de execução foi, em média, 3,315
segundos.
As Figuras 23 e 24 mostram o tempo de execução e o consumo de memória
após a execução do procedimento, respectivamente.
46
Figura 23 - Tempo de execução do
procedimento utilizando ArrayList e LinkedList
7,000
Figura 24 – Consumo de memória do
procedimento utilizando ArrayList e
LinkedList
3,8
4,0
6,157
6,000
4,000
3,315
3,000
2,000
MB
Segundos
2,9
3,0
5,000
2,0
1,0
1,000
0,000
0,0
Tempo de execução
LinkedList
Consumo de memória
ArrayList
Fonte: Autoria própria
LinkedLis
ArrayList
Fonte: Autoria própria
É possível identificar que o consumo de memória da classe ArrayList foi, em
média, 23,68% inferior ao uso da classe LinkedList. Em adição, o tempo de
execução da classe ArrayList foi, em média, 46,16% mais rápida que a classe
LinkedList.
4.4 Utilização de tipos primitivos e classe wrappers
Nesta seção será abordado o uso dos tipos primitivos e classes wrappers.
Pesquisas [17] [23] mostram que as classes wrappers
são mais lentas e
consumem mais memória, devido à sobrecarga adicional de metadados (Class,
Flags e Lock) utilizados pela JVM para descrever o objeto Java. No entanto
esses estudos não mostram a quantidade de memória RAM e tempo de
execução que são desperdiçados.
O primeiro não representa uma classe, mas sim valores básicos. Os tipos
primitivos em Java são byte, short, int, long, float, double, char ou boolean e
ficam armazenados na stack. Já o segundo é armazenado na heap e é utilizado
para referenciar um objeto, esta referência pode ser nula.
47
4.4.1. Cenário
Para realizar as medições, foi desenvolvido um aplicativo Android que continha
pacotes,
AndroidManifest.xml,
InicioActivity.java,
PrimitivoIntActivity.java,
PrimitivoLongActivity.java, ObjetoIntegerActivity.java, ObjetoIntegerActivity.java
e activity_main.xml, sendo detalhados a seguir:
• AndroidManifest.xml: Contempla a declaração de cinco activities;
• InicioActivity.java: Principal activity com quatro botões (int, Integer, long
e Long). O primeiro botão inicia a “PrimitivoIntActvity.java”, o segundo
inicializa
a
“PrimitivoIntegerActvity.java”,
“PrimitivoLongActivity.java”
e
o
o
último
terceiro
direciona
chama
para
“ObjetoLongActivity.java”;
• PrimitivoIntActvity.java: Possuía uma repetição que atribuía em cada
posição de um vetor de int todos os números de 0 (zero) à 24999 (vinte
e quatro mil novecentos e noventa e nove);
• PrimitivoIntegerActvity.java: Continha uma iteração que atribuía em
cada posição de um vetor de Integer todos os números de 0 (zero) à
24999 (vinte e quatro mil novecentos e noventa e nove);
• PrimitivoLongActivity.java: Continha uma repetição que atribuía em
cada posição de um vetor de long todos os números de 0 (zero) à 24999
(vinte e quatro mil novecentos e noventa e nove);
• ObjetoLongActivity.java: Possuía uma iteração que atribuía em cada
posição de um vetor de Long todos os números de 0 (zero) à 24999
(vinte e quatro mil novecentos e noventa e nove);
• activity_main.xml: Arquivo de layout que possuía um LinearLayout com
orientação vertical e quatro botões.
4.4.2. Resultado da avaliação
Esta seção irá efetuar a coleta de dados dos tipos primitivos (int e long) e dos
tipos por referência (Integer e Long).
48
4.4.2.1. Uso de Integer e int
Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir
seu carregamento o botão com o texto “int” foi pressionado.
Esta análise efetua a medição da memória heap antes e depois da execução
do laço mencionado anteriormente. Para a primeira execução o resultado obtido
foi 1,9 MB de memória antes da execução do laço e 2,0 MB de memória após
realização do mesmo.
Esse procedimento foi executado mais quatro vezes e os resultados obtidos
estão listados na Tabela 13.
Tabela 13 – Resultado da execução utilizando o tipo primitivo int
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,0
5,26
0,028
2
1,9
2,0
5,26
0,016
3
1,9
2,0
5,26
0,014
4
1,9
2,0
5,26
0,018
5
1,9
2,0
5,26
0,015
Conclusão
Aumento do consumo de
memória RAM de 5,26%.
Aumento do consumo de
memória RAM de 5,26%
Aumento do consumo de
memória RAM de 5,26%
Aumento do consumo de
memória RAM de 5,26%
Aumento do consumo de
memória RAM de 5,26%
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 5,26%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “int” houve um acréscimo no consumo da heap. Em adição, pode-se
verificar que o tempo de execução foi, em média, 0.018 segundos.
Depois desta execução, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “Integer”. Este procedimento da mesma forma
que o anterior, realizou a medição da memória heap antes e depois da execução
do laço. Na primeira execução, o resultado obtido foi 1.9 MB de memória antes
da execução do laço e 2,4 MB de memória após realização do mesmo.
Esse procedimento, foi executado mais 4 vezes e os resultados obtidos
estão listados na Tabela 14.
49
Tabela 14 – Resultado da execução utilizando a classe wrapper Integer
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,4
26,32
2,617
2
1,9
2,4
26,32
2,422
3
1,9
2,4
26,32
2,533
4
1,9
2,4
26,32
2,396
5
1,9
2,4
26,32
2,457
Conclusão
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 26,32%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “Integer” houve um acréscimo no consumo da heap. Em adição, pode-se
verificar que o tempo de execução foi, em média, 2,485 segundos.
As Figuras 25 e 26 mostram o tempo de execução e o consumo de memória
após a execução do procedimento, respectivamente.
Figura 25 - Tempo de execução do
procedimento utilizando int e Integer
Figura 26 – Consumo de memória do
procedimento utilizando int e Integer
3,000
2,4
2,5
2,485
2,0
2,0
2,000
MB
Segundos
2,500
1,500
1,5
1,0
1,000
0,5
0,500
0,018
0,000
0,0
Tempo de execução
int
Integer
Fonte: Autoria própria
Consumo de memória
int
Integer
Fonte: Autoria própria
É possível identificar que o consumo de memória do tipo primitivo int foi, em
média, 16,67% inferior ao uso da classe wrapper Integer. Em complemento, o
50
tempo de execução do primeiro método foi, em média, 99,28% mais rápido que
o segundo método.
4.4.2.2.
Uso de long e Long
Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir
seu carregamento o botão com o texto “long” foi pressionado.
Esta análise efetua a medição da memória heap antes e depois da execução
do laço mencionado anteriormente. Para a primeira execução o resultado obtido
foi 1.9 MB de memória antes da execução do laço e 2.1 MB de memória após
realização do mesmo.
Esse procedimento foi executado mais quatro vezes e os resultados obtidos
estão listados na Tabela 15.
Tabela 15 - Resultado da execução utilizando o tipo primitivo long
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,1
10,53
0,021
2
1,9
2,1
10,53
0,017
3
1,9
2,1
10,53
0,020
4
1,9
2,1
10,53
0,015
5
1,9
2,1
10,53
0,017
Conclusão
Aumento do consumo de
memória RAM de 10,53%.
Aumento do consumo de
memória RAM de 10,53%.
Aumento do consumo de
memória RAM de 10,53%.
Aumento do consumo de
memória RAM de 10,53%.
Aumento do consumo de
memória RAM de 10,53%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo de memória de, em
média, 10,53%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “long” houve um acréscimo no consumo da heap. Em adição, pode-se
verificar que o tempo de execução foi, em média, 0,018 segundos.
Depois desta execução, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “Long”. Este procedimento da mesma forma
que o anterior, realizou a medição da memória heap antes e depois da execução
51
laço. Na primeira execução o resultado obtido foi 1.9 MB de memória antes da
execução do laço e 2.4 MB de memória após realização do mesmo.
Esse procedimento, foi executado mais 4 vezes e os resultados obtidos
estão listados na Tabela 16.
Tabela 16 - Resultado da execução utilizando a classe wrapper Long
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Tempo de
execução (s)
1
1,9
2,4
26,32
2,075
2
1,9
2,4
26,32
1,793
3
1,9
2,4
26,32
1,964
4
1,9
2,4
26,32
2,066
5
1,9
2,4
26,32
2,107
Conclusão
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 26,32%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “Long” houve um acréscimo no consumo da heap. Em adição, pode-se
verificar que o tempo de execução foi, em média, 2,001 segundos.
As Figuras 27 e 28 mostram o tempo de execução e o consumo de memória
após a execução do procedimento, respectivamente.
Figura 27 - Tempo de execução do
procedimento utilizando long e Long
Figura 28 - Consumo de memória do
procedimento utilizando long e Long
2,001
2,5
2,4
2,1
2,0
1,500
MB
Segundos
2,000
1,000
0,500
0,018
0,000
1,5
1,0
0,5
0,0
Tempo de execução
long
Long
Fonte: Autoria própria
Consumo de memória
long
Long
Fonte: Autoria própria
52
É possível identificar que o consumo de memória do tipo primitivo long foi,
em média, 12,5% inferior ao uso da classe wrapper Long. Em complemento, o
tempo de execução da do primeiro método foi, em média, 99,10% mais rápido
que o segundo método.
4.5 Uso de threads
Existem situações nas quais é preciso executar duas ou mais tarefas ao mesmo
tempo, como por exemplo, em um computador, escutar músicas e escrever um
documento. Em Java, quando o assunto é processamento paralelo fala-se de
Threads [19].
Estudos [36] [37] mostram que o uso inadequado de threads pode causar
vazamento de memória e redução de desempenho.
4.5.1. Cenário
Para realizar as medições, foi desenvolvido um aplicativo Android que continha
pacotes,
AndroidManifest.xml,
InicioActivity.java,
Thread1Activity.java,
Thread2Activity.java, Thread3Activity.java e activity_main.xml, sendo detalhados
a seguir:
• AndroidManifest.xml: Contemplava a declaração de quatro activities;
• InicioActivity.java: Principal activity com três botões (Thread1, Thread2
e Thread3). O primeiro botão iniciava a “Thread1Actvity.java”, o
segundo inicializava a “Thread2Actvity.java” e o ultimo chamava
“Thread3Actvity.java”;
• Thread1Actvity.java: Na criação da activity era instanciada uma nova
thread de longa duração;
• Thread2Actvity.java: Possuía a declaração de uma classe interna,
privada e estática que estendia a classe Thread. Na criação da activity
o método start era invocado;
• Thread3Actvity.java: Possuía a declaração de uma classe interna,
privada e estática que estendia a classe thread. Na criação da activity
53
o método start era invocado. O método onDestroy foi sobrescrito,
implementando uma política para o cancelamento de thread;
• activity_main.xml: Arquivo de layout que possuía um LinearLayout com
orientação vertical e tres botões.
A implementação das classes (Thread1Actvity.java, Thread2Actvity.java e
Thread3Actvity.java) podem ser observadas com mais detalhes no APÊNDICE
A.
4.5.2. Resultado da avaliação
Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir
seu carregamento o botão com o texto “Thread1” foi pressionado, neste
momento uma thread de longa duração foi iniciada, e depois foram efetuadas 10
(dez) rotações de tela, ao efetuar a rotação de tela, a activity atual e destruída e
recriada, porém o Android não irá limpar a memória associada a esta activity,
causando um vazamento de memória e uma redução de desempenho [36].
Quando a política de cancelamento de threads está implementada, não ocorre o
problema mencionado anteriormente.
Esta análise efetua a medição da memória heap antes e depois do processo
mencionado anteriormente. Para a primeira execução o resultado obtido foi: 1,9
MB de memória antes da execução e 2.4 MB de memória após realização do
procedimento.
Esse processo foi executado mais quatro vezes e os resultados obtidos
estão listados na Tabela 17.
54
Tabela 17 - Resultado da execução utilizando uma classe de thread anônima
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Número de
threads
1
1,9
2,4
26,32
11
2
1,9
2,4
26,32
11
3
1,9
2,4
26,32
11
4
1,9
2,4
26,32
11
5
1,9
2,4
26,32
11
Conclusão
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Aumento do consumo de
memória RAM de 26,32%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 26,32%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “Thread1” e rotacionar a tela 10 (dez) vezes houve um acréscimo no
consumo da heap.
Depois desta análise, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “Thread2”, neste momento uma classe interna,
privada e estática que estendia a classe Thread era instanciada e invocava o
método start. Esta análise da mesma forma que a anterior, realizou a medição
da memória heap antes e depois do procedimento mencionado anteriormente.
Na primeira execução o resultado obtido foi 1,9 MB de memória antes da
execução e 2,2 MB de memória após realização do procedimento.
Esse processo, foi executado mais 4 vezes e os resultados obtidos estão
listados na Tabela 18.
55
Tabela 18 - Resultado da execução utilizando uma classe de thread privada e estática que
estendia a classe Thread
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Número de
threads
1
1,9
2,2
15,79
11
2
1,9
2,2
15,79
11
3
1,9
2,2
15,79
11
4
1,9
2,2
15,79
11
5
1,9
2,2
15,79
11
Conclusão
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo de memória de, em
média, 15,79%. Desta forma, pode-se concluir que após pressionar o botão com
o texto “Thread2” e rotacionar a tela (10) dez vezes houve um acréscimo no
consumo da heap.
Depois desta análise, o mesmo processo foi realizado, desta vez,
pressionando o botão com o texto “Thread3”, neste momento uma classe interna,
privada e estática que estendia a classe Thread era instanciada e invocava o
método start. Esta análise da mesma forma que a anterior, realizou a medição
da memória heap antes e depois do procedimento mencionado anteriormente.
Na primeira execução o resultado obtido foi 1,9 MB de memória antes da
execução e 2,2 MB de memória após realização do procedimento.
Esse processo, foi executado mais 4 vezes e os resultados obtidos estão
mencionado na Tabela 19.
56
Tabela 19 - Resultado da execução utilizando uma classe de thread privada e estática que
estendia a classe Thread com política de cancelamento
Ciclo
Memória
antes da
execução
(MB)
Memória
depois da
execução
(MB)
%
Número de
threads
1
1,9
2,2
15,79
1
2
1,9
2,2
15,79
1
3
1,9
2,2
15,79
1
4
1,9
2,2
15,79
1
5
1,9
2,2
15,79
1
Conclusão
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Aumento do consumo de
memória RAM de 15,79%.
Fonte: Autoria própria
É possível verificar que houve um aumento no consumo memória de, em
média, 15,79%. Desta forma pode se concluir que após pressionar o botão com
o texto “Thread3” e rotacionar a tela (10) vez houve um acréscimo no consumo
da heap.
As Figuras 29 e 30 mostram o consumo de memória e quantidade de threads
que foram executadas paralelamente após a execução dos procedimentos,
respectivamente.
Figura 29 - Consumo de memória do
procedimento utilizando threads
Figura 30 – Quantidade de threads
executadas paralelamente
3,0
2,4
2,5
2,2
2,2
Thread
MB
2,0
1,5
1,0
0,5
0,0
Consumo de memória
Modo 1
Modo 2
Modo 3
Fonte: Autoria própria
11
11
10
9
8
7
6
5
4
3
2
1
0
11
1
Quantidade de Threads
Modo 1
Modo 2
Modo 3
Fonte: Autoria própria
É possível identificar que o consumo de memória do modo 1 foi superior
9,09% em média ao consumo de memória dos modos 2 e 3 que foram
57
semelhantes. Em adição, a quantidade de threads do modo 3 foi, em média,
90,91% inferior aos modos 1 e 2 que foram semelhantes.
58
5. CONCLUSÕES
No decorrer deste trabalho, verificou-se que o uso de smartphones estão
crescendo e que 78,6% destes aparelhos utilizam a plataforma Android. Foi
evidenciado que estes dispositivos ainda possuem uma quantidade limitada de
memória física. Devido a este fato, objetivou-se comparar algumas técnicas de
programação já existentes na linguagem Java, a fim de identificar quais poderiam
ser executadas em um menor período de tempo e quais poderiam evitar o
consumo desnecessário de memória RAM.
Dessa forma, foram desenvolvidos aplicativos para a plataforma Android
e efetuada a coleta da memória heap dos aplicativos através da ferramenta
Eclipse MAT. Também foi medido o tempo de execução de cada procedimento
e o número de threads que estavam sendo executadas paralelamente, quando
aplicável. Os resultados obtidos após a realização a análise de dados foram:
a) String X StringBuilder: O consumo de memória RAM das duas classes
foi o mesmo. Em contrapartida, o tempo de execução da segunda classe
foi, em média, 98,62% mais rápido que a primeira classe na concatenação
de textos.
b) Uso de tipos de dados primitivos (adequado e inadequado): A
utilização adequada dos tipos de dados primitivos economizou, em média,
4,35% de memória RAM, porém o tempo de execução foi 10,20% superior
em relação ao uso inadequado dos tipos primitivos.
c) ArrayList X LinkedList: A utilização da primeira classe economizou
23,68% de memória RAM e foi 46,16% mais rápida na inserção de
elementos que a segunda implementação.
d) Classes wrappers (Integer e Long) X Tipo primitivo (int e long):
Evidenciou que a utilização dos tipos dados primitivos (int e long) evitaram
o desperdício de memória RAM de, em média, 16,67% e 12,5%
respectivamente. Em adição o tempo de execução foi mais rápido, em
média, 99,28% e 99,10% respectivamente.
e) Uso de threads: Foi mostrado que ao utilizar uma thread privada, estática
e com uma política de cancelamento foi possível evitar o desperdício de
9,09% de memória RAM e diminuir, em média, 90,91% a quantidade de
threads que estavam sendo executadas paralelamente.
59
Conclui-se que o consumo de memória RAM e o tempo de execução não
estão diretamente relacionados e que é possível escrever códigos que utilizam
recursos diferentes, mas que fazem o mesmo efeito. Dependendo da técnica de
programação utilizada, pode-se evitar o consumo desnecessário de memória
RAM e/ou executar um procedimento em um menor período de execução. Desta
forma, propõe-se algumas sugestões e desafios a serem abordados por
trabalhos futuros:
a) Identificar as vantagens e desvantagens de utilizar técnicas de
programação no desenvolvimento, manutenção e usabilidade de
aplicativos na plataforma Android que podem evitar o consumo
desnecessário de memória RAM e que podem executar suas atividades
mais rapidamente, ou seja, em um menor período de tempo.
b) Analisar e comparar outras técnicas de programação já existentes na
linguagem Java e identificar quais poderão consumir menos memória
RAM e serem executadas em um período menor de tempo.
c) Analisar a relação consumo de memória RAM X consumo de energia.
60
REFERÊNCIAS
[1]
“Vendas de Telefone Celular e Smartphone no Brasil (IDC e Abinee),”
Teleco, 2014. [Online]. Disponível em:
http://www.teleco.com.br/celprod.asp.
[2]
H. Gomes, “Venda de smartphone supera a de celular tradicional pela 1o
vez no Brasil,” Globo, 2013. [Online]. Disponível em:
http://g1.globo.com/tecnologia/noticia/2013/08/venda-de-smartphonesupera-de-celular-tradicional-pela-1-vez-no-brasil.html. [Acesso em: 19Apr-2014].
[3]
“Android and iOS Continue to Dominate the Worldwide Smartphone
Market with Android Shipments Just Shy of 800 Million in 2013, According
to IDC,” IDC, 2014. [Online]. Disponível em:
http://www.idc.com/getdoc.jsp?containerId=prUS24676414. [Acesso em:
19-Apr-2014].
[4]
V. Caputo, “Android e iPhone foram 93,8% dos aparelhos vendidos em
2013,” Exame, 2014. [Online]. Disponível em:
http://exame.abril.com.br/tecnologia/noticias/android-e-iphone-foram-938-dos-aparelhos-vendidos-em-2013.
[5]
G. Beavis, “10 best mobile phones in the world today,” Techradar, 2014.
[Online]. Disponível em: http://www.techradar.com/news/phone-andcommunications/mobile-phones/20-best-mobile-phones-in-the-worldtoday-645440#articleContent. [Acesso em: 20-Apr-2014].
[6]
L. Vogel, “Eclipse Memory Analyzer (MAT) - Tutorial,” vogella, 2013.
[Online]. Disponível em:
http://www.vogella.com/tutorials/EclipseMemoryAnalyzer/article.html#me
mory_heap. [Acesso em: 27-Apr-2014].
[7]
Oracle, “String (Java Platform SE 6),” Oracle. [Online]. Disponível em:
http://docs.oracle.com/javase/6/docs/api/java/lang/String.html. [Acesso
em: 02-Apr-2014].
[8]
Oralce, “Object (Java Platform SE 6),” Oracle. [Online]. Disponível em:
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html. [Acesso
em: 27-Apr-2014].
[9]
G. Guerra, “Introdução a serialização de objetos,” Devmedia. [Online].
Disponível em: http://www.devmedia.com.br/introducao-a-serializacao-deobjetos/3050. [Acesso em: 27-Apr-2014].
[10] Oracle, “CharSequence (Java Platform SE 6),” Oracle. [Online].
Disponível em:
61
http://docs.oracle.com/javase/6/docs/api/java/lang/CharSequence.html.
[Acesso em: 27-Apr-2014].
[11] Oracle, “Comparable (Java Platform SE 6),” Oracle. [Online]. Disponível
em: http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html.
[Acesso em: 27-Apr-2014].
[12] Oracle, “StringBuilder (Java Platform SE 6),” Oracle. [Online]. Disponível
em: http://docs.oracle.com/javase/6/docs/api/java/lang/StringBuilder.html.
[Acesso em: 02-Apr-2014].
[13] Oracle, “Appendable (Java Platform SE 6),” Oracle. [Online]. Disponível
em: http://docs.oracle.com/javase/6/docs/api/java/lang/Appendable.html.
[Acesso em: 27-Apr-2014].
[14] K. Sierra and B. Bates, Use a cabeça! Java, 2nd ed. Rio de Janeiro: Alta
Books, 2005, p. 484.
[15] Oracle, “Primitive Data Types,” Oracle. [Online]. Disponível em:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html.
[Acesso em: 06-Apr-2014].
[16] “Collections framework,” Caelum. [Online]. Disponível em:
http://www.caelum.com.br/apostila-java-orientacao-objetos/collectionsframework/#16-2-listas-java-util-list. [Acesso em: 05-Apr-2014].
[17] C. Bailey, “Do Código Java ao Heap Java,” IBM, 2012. [Online].
Disponível em: http://www.ibm.com/developerworks/br/library/jcodetoheap/. [Acesso em: 05-Jan-2014].
[18] R. Lanhellas, “Diferença entre ArrayList, Vector e LinkedList em Java,”
Devmedia. [Online]. Disponível em:
http://www.devmedia.com.br/diferenca-entre-arraylist-vector-e-linkedlistem-java/29162. [Acesso em: 05-Apr-104AD].
[19] M. Palheta, “Threads,” Gloogle, 2011. [Online]. Disponível em:
https://sites.google.com/site/marciopalheta/treinamentosjava/treinamentos-jse/14.Threads.pdf?attredirects=0&d=1. [Acesso em:
06-Apr-2014].
[20] Oracle, “Thread (Java Platform SE 6),” Oracle. [Online]. Disponível em:
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html. [Acesso
em: 06-Apr-2014].
[21] Caelum, “Programação Concorrente e Threads,” Caelum. [Online].
Disponível em: http://www.caelum.com.br/apostila-java-orientacaoobjetos/programacao-concorrente-e-threads/#17-1-threads. [Acesso em:
06-Apr-2014].
[22] Deitel, Java - Como Programas. Pearson, 2005, p. 1152.
62
[23] R. Lanhellas, “Introdução aos Wrappers em Java,” Devmedia. [Online].
Disponível em: http://www.devmedia.com.br/introducao-aos-wrappersem-java/28605. [Acesso em: 06-Apr-2014].
[24] R. Lecheta, Google Android, 2nd ed. São Paulo: Novatec, 2010, p. 608.
[25] C. E. Tosin, “Conhecendo o Android,” 2011. [Online]. Disponível em:
http://www.softblue.com.br/blog/home/postid/11/CONHECENDO+O+AND
ROID. [Acesso em: 13-Apr-2014].
[26] C. E. Tosin, “Memory Leak em Java ?,” 2008.
[27] C. C. Prodanov and F. C. De, Metodologia da pesquisa e elaboração de
dissertação, 4th ed. Florianópolis: UFSC, 2013, p. 277.
[28] R. K. Yin, Estudo de caso: planejamento e métodos, 2nd ed. Porto
Alegre: Book-man, 2001.
[29] A. C. Gil, Como Elaborar Projetos de Pesquisa, 4th ed. São Paulo: Atlas,
p. 176.
[30] “Eclipse Memory Analyzer Open Source Project,” Eclipse. [Online].
Disponível em: https://www.eclipse.org/mat/. [Acesso em: 15-Jan-2014].
[31] “Série 5 - 530U3C-AD5 - GERAL | SAMSUNG,” Samsung. [Online].
Disponível em: http://www.samsung.com/br/consumer/itproducts/notebooks-netbooks/ultra-portable/NP530U3C-AD5BR. [Acesso
em: 16-Jan-2014].
[32] C. Vinicius, “Java: Diferenças entre as classes String, StringBuffer e
StringBuilder,” Oficina da NET. [Online]. Disponível em:
http://www.oficinadanet.com.br/post/2124java_diferencas_entre_as_classes_string_stringbuffer_e_stringbuilder.
[Acesso em: 05-Apr-2014].
[33] P. Silveira, “Revisitando a concatenação de Strings: StringBuilder e
StringBuffer,” Caelum, 2010. [Online]. Disponível em:
http://blog.caelum.com.br/revisitando-a-concatenacao-de-stringsstringbuilder-e-stringbuffer/. [Acesso em: 01-Apr-2014].
[34] M. Junior, “Tipos Primitivos - Java,” Java com café. [Online]. Disponível
em: http://www.javacomcafe.com/2010/07/tipos-primitivos-java.html.
[35] X Wang, “ArrayList vs. LinkedList vs. Vector,” Programcreek. [Online].
Disponível em: http://www.programcreek.com/2013/03/arraylist-vslinkedlist-vs-vector/. [Acesso em: 05-Jan-2014].
[36] A. Lockwood, “Activitys, Threads, & Memory Leaks,”
Androiddesignpatterns, 2013. [Online]. Disponível em:
63
http://www.androiddesignpatterns.com/2013/04/activitys-threads-memoryleaks.html. [Acesso em: 20-Mar-2014].
[37] M. Brylski, “Leaking Thread,” Modelrefactoring, 2013. [Online]. Disponível
em:
http://www.modelrefactoring.org/smell_catalog/smells/leaking_thread.html
. [Acesso em: 21-Mar-2014].
[38] M. S. Vaz, “Introdução a Metadados,” Devmedia. [Online]. Disponível em:
http://www.devmedia.com.br/introducao-a-metadados/1883.
64
APÊNDICES
APÊNDICE A – Modos de threads analisados no experimento
Figura 31 - Utilizando uma classe de thread privada e estática que estende a classe Thread
com política de cancelamento
Fonte: Autoria própria
65
Figura 32 – Utilizando uma classe de thread anônima
Fonte: Autoria própria
Figura 33 - Utilizando uma classe de thread privada e estática que estende a classe Thread
Fonte: Autoria própria
Download

View/Open