Documentos de Académico
Documentos de Profesional
Documentos de Cultura
1. Introdução
Muitas linguagens de programação provêem coleta de lixo a fim de desalocar
automaticamente objetos incessíveis. Os coletores de lixo livram o programador da
responsabilidade de desalocar a memória, simplificando assim a implementação de
algoritmos complexos e eliminando os erros por falta de memória que são difíceis de
detectar e reparar. Quando estamos lidando com apenas um processo, o gerenciamento
do heap dinâmico já é bastante suscetível a erros. A questão fica impraticável com o
aumento da complexidade do sistema, como no caso de um heap compartilhado por
várias aplicações escritas por programadores diferentes, acessado em paralelo e com
acesso distribuído.
Com sua importância já bem fundamentada no gerenciamento local de memória, é
natural se beneficiar dos coletores de lixo também em ambientes distribuídos. As
motivações para tal serviço são inúmeras. Sistemas distribuídos modernos provêem
alocação e invocação uniforme e transparente de objetos locais e remotos. Da mesma
forma, tais sistemas também devem prover transparência no gerenciamento de objetos,
o que é alcançado através de um coletor de lixo distribuído. Além disso, o
gerenciamento de memória é uma tarefa extremamente complexa e não deve ser uma
responsabilidade do programador.
Esta monografia está organizada como a seguir. A sessão 2 descreve os fundamentos
básicos relacionados à coleta de lixo local e distribuída, assim como as técnicas mais
conhecidos. A sessão 3 caracteriza os algoritmos de coleta de lixo distribuída iniciais,
mostrando suas diferenças e seus elementos em comum e também quais eram suas
principais preocupações. A seguir, é feita uma análise de alguns algoritmos mais atuais
de coleta de lixo distribuída, mostrando em as mudanças no foco principal e como o
objetivo se tornou muito mais específico. Por fim, são apresentadas as conclusões deste
trabalho.
2. Fundamentos
Coleta de lixo [Jones, 1996] é uma forma automática de realizar gerenciamento de
memória. Com este recurso, é possível recuperar zonas de memória que o programa não
utiliza mais. Enquanto, em muitos sistemas, os programadores devem gerenciar
explicitamente a memória, utilizando, por exemplo, as declarações “free” ou “dispose”,
sistemas com coletores de lixo livram o programador desse fardo. A função do coletor
de lixo é achar objetos de dados que não são mais usados e tornar seu espaço de
armazenamento disponível para reuso pelo programa em execução. Um objeto é
considerado lixo caso não existam referências para ele. Neste caso, o coletor de lixo irá
marcar para desalocação a área de memória onde reside tal objeto. Objetos vivos
(potencialmente alcançáveis) são preservados pelo coletor, assegurando que o programa
nunca terá uma referência para um objeto desalocado.
A coleta de lixo automática elimina a grande quantidade de erros que podem ser
introduzidos pelo programador quando este deve gerenciar explicitamente a memória.
Além disso, permite uma programação mais modular, já que um módulo não precisa
saber se um objeto está sendo referenciado por outros módulos para que possa coletá-lo,
ou não, explicitamente. Não desalocar a memória no momento correto pode acarretar
erros como memory leak (vazamento de memória), onde objetos não mais referenciados
pelo programa em execução foram sendo acumulados na memória até que não houvesse
mais espaço de armazenamento. Devido ao custo extra do gerenciamento manual de
memória, sistema sem coleta de lixo automática são mais difíceis de desenvolver e de
manter.
Por estes motivos, linguagens que possuem coleta de lixo automática há muito tempo
vêm sendo usadas para a implementação de algoritmos sofisticados que utilizam
estruturas de dados complexas. O funcionamento básico de um coletor de lixo consiste
de duas fases:
1. Distinguir de alguma forma o lixo dos objetos vivos (detecção de lixo);
2. Desalocar a memória ocupada pelos objetos considerados lixo para que o
programa possa reusá-la (desalocação de memória).
Na prática, essas duas fases podem ser temporariamente e funcionalmente intercaladas.
Além disso, a fase de desalocação de memória depende fortemente a técnica de
detecção de lixo. As duas sessões 2.1 e 2.2 a seguir descrevem os principais algoritmos
de coleta de lixo local e distribuída respectivamente.
2.1.3 Copying
O algoritmo copying não coleta o lixo propriamente, ao invés disso, ele move todos os
objetos vivos para uma área e notifica o sistema que o resto to heap está disponível para
reuso, pois contém apenas lixo. Enquanto o algoritmo mark-compact usa uma terceira
fase para mover os objetos, o algoritmo copying integra o rastreamento dos dados com o
processo de cópia. À medida que vão sendo visitados pelo rastreamento, os objetos são
movidos para uma área adjacente da memória. Assim é possível eliminar o problema da
fragmentação de memória de forma mais eficiente.
2.1.4 Outras técnicas
Além dos algoritmos básicos, ainda existem as técnicas incrementais e generacionais.
As técnicas incrementais permitem que a coleta de lixo seja realizada a curtos passos,
intercalada com a execução da aplicação. Essas técnicas podem reduzir o impacto da
inicialização da coleta de lixo, já que o programa não precisa parar e esperar que a
coleta termine. Isso possibilita o uso de coletores de lixo em sistemas de tempo real. As
técnicas incrementais também podem ser generalizadas a fim de realizar coletas
concorrentes que são executadas em outro processador e em paralelo com a execução do
programa.
As técnicas generacionais aumentam a eficiência e a localidade realizando a coleta de
lixo em uma área menor e mais frequentemente. Essas técnicas exploram o tempo de
vida dos objetos para evitar o trabalho extra ocorrido no tratamento de objetos com um
longo tempo de vida. Como a maioria das coletas são realizadas em pequenas áreas, os
momentos em que o programa pausa para a coleta são curtos. Para muitas aplicações, as
técnicas generacionais são uma razoável alternativa às técnicas incrementais.
4. Preocupações Atuais
Sem dúvida, a coleta de lixo distribuída é uma área onde podem ocorrer mudanças
rápidas e possivelmente drásticas. A tecnologia na área de redes evolui rapidamente,
levando a construção de sistemas distribuídos cada vez mais sofisticados. O requisito de
transparência deve ser levado ao extremo, permitindo a implementação de poderosos
sistemas distribuídos que irão rodar sobre uma camada de coleta de lixo distribuída de
um protocolo de comunicação.
É muito difícil falar dos algoritmos de coleta de lixo distribuída sem correr o risco de
levantar questões relativas à evolução da tecnologia de redes. É razoável assumir que,
em uma rede local, a comunicação é confiável, de baixo custo e bastante rápida.
Também é possível assumir a existência de algum tipo de sincronização global. Assim,
os algoritmos de coleta de lixo distribuída para redes locais, como os citados acima,
podem ser vistos como uma extensão dos algoritmos de coleta de lixo local. Embora
não seja explicitamente mencionado na literatura, é justo dizer que quase todos os
algoritmos de coleta de lixo até 1995, ano de publicação do trabalho de Plainfossé e
Shapiro [Plainfossé, 1995], visam redes locais, pois assumem que as mensagens sempre
são entregues, que o custo de envio é relativamente baixo ou que existe algum
mecanismo de sincronização. Algoritmos que pretendem rodar em WANs (Wide Área
Networks) não podem fazer tais suposições. Porém, à medida que a tecnologia evolui,
as máquinas e as redes se tornam mais velozes e confiáveis. Um problema
computacional que hoje é endereçado por uma rede local pode amanhã estar rodando
sobre uma WAN. A mesma escala evolucionária se aplica a protocolos de coleta de lixo
distribuída.
Algoritmos atuais de coleta de lixo distribuída possuem um enfoque bastante diferente
dos inicias. Por exemplo, eles não mais se preocupam em determinar quando iniciar a
coleta de lixo. Alguns deles, ao invés de se basearem em um sistema orientado a
objetos, procuram tratar de outros tipos de entidades, como atores. Essas entidades
possuem um comportamento bastante diferente dos objetos passivos comuns. As
mesmas regras usadas para se determinar se um objeto é lixo não podem ser
consideradas num sistema de atores, como pode ser visto na sessão 4.1.
Outros trabalhos apresentam algoritmos que procuram resolver o problema da
sincronização, não assumindo a existência de um relógio global ou uma troca de
mensagens confiável. Como exemplo, podemos citar o trabalho de Veiga e Ferreira
[Veiga, 2005] que descreve um algoritmo de coleta de lixo distribuída capaz de coletar
ciclos distribuídos de forma assíncrona e eficiente, sem necessitar de nenhum tipo de
coordenação entre espaços e tolerando perda de mensagens. Na sessão 4.2, é
apresentado um trabalho que trata de checkpoints ao invés de objetos e toma como
principal requisito o assincronismo, mostrando claramente como os algoritmos foram se
tornando mais específicos.
4.1 Coleta de Lixo Distribuída para Sistemas de Atores Móveis
O conceito de atore unifica as noções de processo (thread de controle), memória
(variáveis encapsuladas) e comunicação (troca de mensagens). Atores são objetos
atualmente ativos. Não existem entidades passivas. Cada ator é unicamente identificado
pelo endereço de sua caixa de mensagens. Atores-raiz são aqueles designados para estar
sempre em execução e também aqueles que podem interagir com o mundo externo, via
mecanismo de entrada e saída por exemplo. Um ator pode estar desbloqueado, quando
está processando uma mensagem ou quando possui mensagens em sua caixa, ou pode
estar bloqueado. A comunicação entre atores e puramente assíncrona, no entanto, a
comunicação é garantida, todas as mensagens são eventualmente enviadas e recebidas.
Existe uma dificuldade adicional enfrentada por um coletor de lixo para atores:
simplesmente seguir as referências a partir dos atores-raiz não garante que todo o lixo
será detectado. A figura 1 mostra a diferença entre um sistema de coleta de lixo baseado
em objetos passivos e um sistema baseado em atores. Essa figura foi extraída do
trabalho de Wang e Varela [Wang, 2006] que usa uma abordagem chamada pseudo-raíz
para tratar a coleta de lixo em sistemas baseados em atores. Nessa abordagem, os
autores introduzem um conjunto de pseudo-raízes dinâmicas que podem ser vista como
o conjunto raiz da coleta de lixo. As pseudo-raízes usam referências protegidas (que não
podem ser apagadas) para assegurar que atores não sejam coletados erroneamente,
mesmo com mensagens em trânsito.
8 1 2 3 4
9 5 6 7
8 1 2 3 4
9 5 6 7
Figura 1. Os atores 3, 4 e 8 estão vivos, pois podem enviar mensagens para os atores-
raíz. Os Objetos 3, 4 e 8 são lixo, pois não podem ser alcançados a partir da raíz.
Um ator pode ser considerado lixo quando ele não mais interage com o sistema, mas
continua consumindo memória e tempo de processamento. Sendo assim, um ator é
considerado lixo quando não está mais ativo e nem pode se tornar ativo no futuro ou
quando não pode mais enviar mensagens para os atores-raiz e nem receber mensagens
dos mesmos. A propriedade chave de um ator considerado lixo é que ele não pode
deixar de ser lixo. Isso se deve pelo fato de não é mais possível para esses atores se
comunicarem com atores-raiz.
5. Conclusão
Algoritmos de coleta de lixo distribuída são essenciais para a implementação de
sistemas distribuídos sofisticados. Inicialmente, ao partir para um ambiente distribuído,
tentou-se fazer uma tradução direta dos algoritmos básicos de coleta de lixo local para
algoritmos de coleta de lixo distribuída. Sendo assim, os algoritmos iniciais podem ser
vistos como uma extensão dos algoritmos básicos de coleta de lixo local. Esse trabalho
apresentou uma análise das semelhanças e diferenças dos algoritmos iniciais de coleta
de lixo distribuída e também quais eram as primeiras preocupações da área.
Ao saltar anos à frente, podemos observar a mudança de foco na área de coleta de lixo
distribuída. Os algoritmos se tornam mais específicos, procurando não tratar de objetos
em geral, mas de outras entidades que possuem um comportamento diferente dos
objetos. Também é possível notar que os algoritmos mais recentes evitam fortes
suposições sobre a infra-estrutura de rede, como a existência de um relógio global e
uma troca de mensagens confiável. Alguns deles, por exemplo, passam a dar um grande
enfoque ao problema do assincronismo.
Referências
[Hughes, 1985] John Hughes. A distributed garbage collection algorithm. Nos anais
da ACM Conference on Functional Programming Languages and Computer
Architecture, número 201 da série Lecture Notes in Computer Science,
páginas 256-272, Nacy, França, Software Practice and Experience 1985.
Springer-Verlag.
[Jones, 1996] Richard Jones e Rafael Lins. (1996), Garbage Collection: Algorithms
for Automatic Dynamic Memory Management, Wiley, 1a edição.
[Lermen, 1986] C.W. Lermen e Dieter Maurer. A protocol for distributed reference
counting. Em [LFP, 1986], páginas 343-350.
[Liskov, 1986] Barbare Liskov e Rivka Ladin. Highly available distributed services
and fault-tolerant distributed garbage collection. Nos anais do 5o Annual
Symposium on the Principles on Distributed Computing, páginas 29-39.
Calgary, agosto de 1986. ACM Press.
[Plainfossé, 1995] David Plainfossé e Marc Shapiro. A survey of distributed garbage
collection techiniques. Nos anais do International Workshop on Memory
Management. Kinross, Escócia, Setembro de 1995.
[Rana, 1983] S. P. Rana. A distributed solution to the distributed termination
problem. Information Processing Letters, 17:43-46, julho de 1983.
[Schmidt, 2005] Rodrigo Schmidt, Islene C. Garcia, Fernando Pedone e Luiz E.
Buzato. Optimal asynchronous garbage collection for RDT checkpointing
protocols. Nos anais da 25a International Conference on Distributed
Computing Systems (ICDCS'05). Columbus, Ohio, EUA, Junho de 2005
[Veiga, 2005] Luís Veiga e Paulo Ferreira. Asynchronous complete distributed
garbage collection. Nos anais do 19o IEEE International Parallel and
Distributed Processing Symposium (IPDPS’05).
[Wang, 2006] Wei-Jen Wang e Carlos A. Varela. Distributed garbage collection for
mobile actor systems: the pseudo root aproach. Nos anais da 1a International
Conference on Grid and Pervasive Computing (GPC 2006), volume 3947 de
Lecture Notes in Computer Science, páginas 360-372, Taichung, Taiwan,
Maio de 2006.
[Wilson, 1992] Paul R. Wilson. Uniprocessor garbage collection techniques. Nos
anais do International Workshop on Memory Management na série Lecture
Notes in Computer Science. St. Malo, França, Setembro de 1992. Springer-
Verlag.