Por métodos de coleta de lixo Java e Python são diferentes?

votos
47

Python usa o método de contagem de referência para lidar com o tempo de vida do objeto. Portanto, um objeto que não tem mais uso será imediatamente destruída.

Mas, em Java, o GC (coletor de lixo) destrói objetos que não são mais usados ​​em um momento específico.

Por que Java escolher esta estratégia e qual é o benefício disso?

É melhor do que a abordagem Python?

Publicado 22/08/2008 em 08:35
fonte usuário
Em outras línguas...                            


9 respostas

votos
43

Existem desvantagens do uso de contagem de referência. Um dos mais mencionado é referências circulares: Suponha Um referências B, B referencia C e C referencia B. Se A desistir da sua referência para B, B e C ainda terá uma contagem de referência de 1 e não serão suprimidos com a contagem de referência tradicional. CPython (contagem de referência não faz parte da própria pitão, mas parte da aplicação dos mesmos C) pega referências circulares com uma rotina de recolha de lixo separado que ele é executado periodicamente ...

Outra desvantagem: Contagem de referência pode tornar a execução mais lenta. Cada vez que um objeto é referenciado e dereferenced, o intérprete / VM deve verificar para ver se a contagem caiu para 0 (e depois desalocar se fez). A coleta de lixo não precisa fazer isso.

Além disso, a coleta de lixo pode ser feito em um segmento separado (embora possa ser um pouco complicado). Em máquinas com muita memória RAM e para processos que usam memória apenas lentamente, você pode não querer estar fazendo GC em tudo! Contagem de referência seria um pouco de problema lá em termos de desempenho ...

Respondeu 22/08/2008 em 10:10
fonte usuário

votos
26

Na verdade contagem de referência e as estratégias utilizadas pela Sun JVM são todos diferentes tipos de algoritmos de coleta de lixo.

Existem duas grandes abordagens para rastrear objetos mortos: rastreamento e contagem de referência. Ao traçar o GC começa a partir das "raízes" - coisas como referências pilha, e traça tudo (ao vivo) objetos acessíveis. Qualquer coisa que não pode ser alcançado é considerado morto. Na contagem de referência cada vez que uma referência é modificado o objeto de envolvidos têm sua contagem atualizada. Qualquer objeto cuja contagem de referência é definido a zero é considerado morto.

Com basicamente todas as implementações de GC existem trade-offs, mas o rastreamento é geralmente bom para alta através de uma operação colocar (ou seja rápido), mas tem mais tempos de pausa (lacunas maiores, onde a interface do usuário ou programa pode congelar-se). Contagem de referência pode operar em pedaços menores, mas será mais lento em geral. Isso pode significar menos congela, mas mais pobre desempenho global.

Além disso, uma contagem de referência CG requer um detector de ciclo para limpar quaisquer objectos em um ciclo que não vai ser apanhado pela sua contagem de referência sozinho. Perl 5 não tem um detector de ciclo na sua implementação GC e pode vazar memória que era cíclica.

A pesquisa também tem sido feito para obter o melhor dos dois mundos (os tempos de baixa pausa, alto rendimento): http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/urc-oopsla-2003.pdf

Respondeu 13/10/2008 em 02:42
fonte usuário

votos
13

Darren Thomas dá uma boa resposta. No entanto, uma grande diferença entre o Java e Python abordagens é que, com a contagem de referência no caso comum (sem referências circulares) objetos são limpos imediatamente, em vez de em alguma data posterior indeterminado.

Por exemplo, eu posso escrever código desleixado, não-portáteis em CPython como

def parse_some_attrs(fname):
    return open(fname).read().split("~~~")[2:4]

e o descritor de arquivo para esse arquivo Abri serão limpos imediatamente porque assim que a referência para o arquivo aberto vai embora, o arquivo é lixo coletado e o descritor de arquivo é liberado. Claro, se eu executar Jython ou IronPython ou possivelmente PyPy, em seguida, o coletor de lixo não vai necessariamente funcionar até muito mais tarde; possivelmente eu vou correr para fora de descritores de arquivos primeiro e meu programa irá falhar.

Então você deve escrever código que parece

def parse_some_attrs(fname):
    with open(fname) as f:
        return f.read().split("~~~")[2:4]

mas às vezes as pessoas gostam de contar com a contagem de referência para sempre liberar seus recursos porque às vezes pode tornar o código um pouco mais curto.

Eu diria que o melhor coletor de lixo é aquele com o melhor desempenho, que atualmente parece ser a Java de estilo coletores de lixo de gerações que podem ser executados em um segmento separado e tem todas essas otimizações loucas, etc. As diferenças de como você escrever seu código deve ser insignificante e, idealmente, inexistente.

Respondeu 22/08/2008 em 13:40
fonte usuário

votos
8

Eu acho que o artigo " Java teoria e prática: Uma breve história da coleta de lixo " da IBM pode ajudar a explicar algumas das perguntas que você tem.

Respondeu 22/08/2008 em 08:40
fonte usuário

votos
5

A coleta de lixo é mais rápido (mais tempo eficiente) do que a contagem de referência, se você tem memória suficiente. Por exemplo, um gc cópia atravessa os objetos e as copia "ao vivo" para um novo espaço, e pode recuperar todos os objetos "mortos" em uma única etapa, marcando uma região de memória todo. Isto é muito eficiente, se você tem memória suficiente. Coleções geracionais usar o conhecimento de que "a maioria dos objetos morrer jovem"; muitas vezes, apenas uma pequena percentagem de objetos têm de ser copiado.

[Esta é também a razão pela qual gc pode ser mais rápido que malloc / livre]

Contagem de referência é muito mais eficiente do espaço de coleta de lixo, uma vez que recupera a memória do momento ele fica inacessível. Isso é bom quando você deseja anexar finalizadores a objetos (por exemplo, para fechar um arquivo uma vez que o objeto de arquivo fica inacessível). Um sistema de contagem de referência pode funcionar mesmo quando apenas uma pequena percentagem da memória está livre. Mas o custo de ter de gestão para incrementar e contadores decréscimo sobre cada atribuição ponteiro custar muito tempo, e algum tipo de coleta de lixo ainda é necessária para recuperar ciclos.

Assim, o trade-off é clara: se você tem que trabalhar em um ambiente com limitações de memória, ou se precisar de finalizadores precisas, usar contagem de referência. Se você tem memória suficiente e precisa da velocidade, usar a coleta de lixo.

Respondeu 16/09/2008 em 17:38
fonte usuário

votos
3

Uma grande desvantagem do GC rastreamento de Java é que de vez em quando ele vai "parar o mundo" e congelar o pedido de um tempo relativamente longo para fazer um GC completo. Se a pilha é grande eo complexo objeto da árvore, ele irá congelar por alguns segundos. Além disso, cada GC completo visita a árvore inteira objeto uma e outra vez, algo que é provavelmente muito ineficiente. Outra desvantagem do caminho Java faz GC é que você tem que dizer a JVM que tamanho da pilha você quer (se o padrão não é bom o suficiente); JVM deriva a partir deste valor vários limiares que desencadeiam o processo de GC, quando existe muito lixo empilhamento acima na pilha.

Presumo que esta é realmente a principal causa do sentimento espasmódico do Android (baseado em Java), mesmo nos celulares mais caros, em comparação com a lisura do iOS (baseado em ObjectiveC, e usando RC).

Eu adoraria ver uma opção JVM para ativar o gerenciamento de memória RC, e talvez manter GC apenas para executar como um último recurso, quando não há mais memória esquerda.

Respondeu 19/10/2011 em 19:40
fonte usuário

votos
2

Contagem de referência é particularmente difícil de fazer de forma eficiente em um ambiente multi-threaded. Eu não sei como você pode até começar a fazê-lo sem entrar em transações de hardware assistida ou (atualmente) instruções atômicas incomuns semelhantes.

Contagem de referência é fácil de implementar. JVMs ter tido um monte de dinheiro afundado em implementações concorrentes, por isso não deve ser surpreendente que eles implementam muito boas soluções para problemas muito difíceis. No entanto, está se tornando cada vez mais fácil para atingir o seu idioma preferido no JVM.

Respondeu 05/09/2008 em 21:03
fonte usuário

votos
2

A mais recente Sun Java VM realmente tem vários algoritmos de GC que você pode ajustar. As especificações Java VM omitido intencionalmente especificando comportamento real GC para permitir diferentes (e múltiplas) algoritmos de GC para VMs diferentes.

Por exemplo, para todas as pessoas que não gostam da abordagem "stop-the-world" do comportamento GC Sun Java VM padrão, existem VM, como IBM WebSphere Real Time , que permite a aplicação em tempo real para rodar em Java.

Desde a especificação Java VM está disponível publicamente, não é (teoricamente) nada que impeça qualquer pessoa de implementação de um VM Java que usa algoritmo de GC de CPython.

Respondeu 22/08/2008 em 23:58
fonte usuário

votos
1

No final do jogo, mas eu acho que um raciocínio significativo para RC em python é a sua simplicidade. Veja este e-mail por Alex Martelli , por exemplo.

(Eu não poderia encontrar um link fora do cache do Google, a data e-mail a partir de 13 de outubro de 2005 na lista python).

Respondeu 22/10/2009 em 02:11
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more