• Nenhum resultado encontrado

Algoritmo de contagem de referência cíclica com o uso da Jump-stack

2.4 Algoritmos em ambiente monoprocessado

2.4.3 Contagem de referências cíclicas

2.4.3.6 Algoritmo de contagem de referência cíclica com o uso da Jump-stack

Lins [Lin02a] introduziu uma nova estrutura de dados, uma pilha, denominada Jump-stack, que armazena referências a “pontos críticos” do grafo durante a fase de marcação local após a exclusão de uma referência para uma célula compartilhada. O novo algoritmo em vez de retornar ao início do mark-scan, ele “salta” diretamente o grafo, analisando os pontos críticos de imediato, evitando chamadas desnecessárias ao procedimento Scan.

O algoritmo funciona em duas fases. Na primeira fase, o sub-grafo da referência removida é percorrido para ajustar os contadores para que espelhem apenas as referências externas e as células são pintadas de vermelho, ficando marcadas como já visitadas. Toda vez que uma célula, que tem seu contador de referência diferente de zero, for excluída, fará com que o algoritmo armazene na Jump-stack todas as células que potencialmente estão transitivamente vinculadas à raiz. Na segunda fase, as células apontadas pelas referências contidas na Jump-stack são visitadas de forma direta. Se uma célula que está sendo analisada permanecer com o contador maior que zero, o sub-grafo inteiro sob ela está em uso e precisa ter os contadores de suas células reajustados. Na parte final dessa fase, será realizada a coleta das células não mais referenciadas. Não é mais necessário percorrer as células lixo pintadas de

Algoritmo 2.17 O procedimento Mark-red do algoritmo de contagem de referências cíclicas com mark-scan lazy

azul. O lixo que eventualmente existir será recolhido de forma direta pelo procedimento

Collect depois do processamento da Jump-stack. Neste caso, a fase de Scan é poupada o

máximo possível.

2.4.3.7 Algoritmo de contagem de referência cíclica com o uso da Jump-stack -

procedimentos

Delete(<R,S>): É idêntico ao algoritmo estrito, diferenciando no fato que os procedimentos

Mark-red e Scan são invocados nas últimas linhas do algoritmo.

Delete(<R,S>) = Remove <R,S> if (RC(S) == 1) then for T in Sons(S) do Delete(<S,T>) Link-to-free-list(S) else Decrement RC(S) Mark-red(S) Scan(S)

Mark-red(S): Em seu código que está embutido a otimização do algoritmo com o uso da Jump-stack. Armazenando as possíveis referências externas ao sub-grafo, evitando-se assim que o procedimento Scan percorra uma área de lixo para pintar as células de azul desnecessariamente. Com o processamento da Jump-stack, se restar alguma célula, é lixo que pode ser coletado diretamente.

Algoritmo 2.18 O procedimento Delete do algoritmo de contagem de referências cíclicas com o uso da Jump-stack

Mark-red(S) =

if (colour(S) == green) then colour(S) = red

for T in Sons(S) do Decrement RC(T)

if (RC(T) > 0 && T not in Jump-stack) then Push-Jump-stack(T)

if (colour(T) == green) then Mark-red(T)

Scan(S): Verifica se a Jump-stack tem algum elemento. Se estiver vazia, as células sob S são vinculadas à free-list por meio do procedimento Collect. Se existir algum elemento na

Jump-stack, significa que ainda existem células no sub-grafo a serem analisadas. Se estas

células têm seus contadores de referências maiores que zero, então há ainda referências externas que as vinculam transitivamente à raiz e estes contadores têm que ser reajustados. Este reajuste é realizado pelo procedimento Scan-green, que continua sendo o mesmo.

Scan(S) =

if (RC(S) > 0) then Scan-green(S) else

while (Jump-stack not empty) do T = top-of-Jump-stack

Pop-Jump-stack

if (colour(T) == red && RC(T) > 0) then Scan-green(T)

Collect(S)

Algoritmo 2.19 O procedimento Mark-red do algoritmo de contagem de referências cíclicas com o uso da Jump-stack

Algoritmo 2.20 O procedimento Scan do algoritmo de contagem de referências cíclicas com o uso da Jump-stack

Collect(S): Verifica células de cor vermelho (células lixo) e as retorna para a free-list.

Collect(S) =

if (colour(S) == red) then for T in Sons(S) do Remove(<S,T>) RC(S) = 1

colour(S) = green Link-to-free-list(S)

if (colour(T) == red) then Collect(T)

Um melhoramento neste algoritmo ainda foi obtido otimizando-se o uso da Jump-stack, de forma a postergar a inserção de referências e, com isso, garantir uma única tentativa de inserção para cada elemento do sub-grafo. Esta otimização está incluída no procedimento

Mark-red, de modo que na chamada de S, sua inserção só é definida após a chamada recursiva

do procedimento para seus filhos em Sons(S). Desta forma, a decisão de incluir um elemento na Jump-stack é procastinada e, se esta inclusão acontecer, será realizada uma única vez. Observe o Algoritmo 2.22 do procedimento Mark-red.

Mark-red(S) =

if (colour(S) == green) then colour(S) = red

for T in Sons(S) do Decrement RC(T)

if (colour(T) == green) then Mark-red(T)

if (RC(S) > 0) then Push-Jump-stack(T)

Nos cenários dos algoritmos com o mark-scan estrito e lazy com a Jump-stack, analisaremos novamente duas situações onde o mark-san local é processado. A diferença entre o algoritmo estrito e o lazy, reside no fato de que o segundo posterga o processamento local através do uso do Control-set.

Algoritmo 2.21 O procedimento Collect do algoritmo de contagem de referências cíclicas com o uso da Jump-stack

Algoritmo 2.22 Novo procedimento Mark-red do algoritmo de contagem de referências cíclicas com o uso otimizado da Jump-stack

No algoritmo lazy, quando se executa o procedimento Scan-control-set, o mark-can utiliza a Jump-stack do mesmo modo que o estrito. Com isso, os cenários analisados a seguir, são válidos para os dois casos com a Jump-stack.

No primeiro caso, mostraremos o comportamento do algoritmo na estrutura mínima do grafo mostrada na tese de mestrado de Salkild [Sal87] que encontrou uma falha no algoritmo de contagem de referências cíclicas proposto por Brownbridge [Bro85] em 1985. Nessa estrutura, não há células a serem reclamadas quando um ponteiro que vincula a raiz a uma célula é excluído. No segundo caso, mostraremos o comportamento do algoritmo quando os dois ponteiros que ligam a raiz à estrutura são excluídos, fazendo com que as células do grafo que formam o ciclo sejam vinculadas à free-list através do procedimento mark-scan local que utiliza a Jump-stack para evitar as chamadas recursivas desnecessárias ao Scan.

Documentos relacionados