Hvorfor Java og Python søppelrydding metoder er annerledes?

stemmer
48

Python bruker referansetelle-metode for å håndtere objektet levetid. Så et objekt som ikke har mer bruk vil bli umiddelbart ødelagt.

Men, i Java, GC (garbage collector) ødelegger gjenstander som ikke lenger brukes på et bestemt tidspunkt.

Hvorfor Java velger denne strategien, og hva er fordelen av dette?

Er dette bedre enn Python tilnærming?

Publisert på 22/08/2008 klokken 07:35
kilden bruker
På andre språk...                            


9 svar

stemmer
43

Det er ulempene med å bruke referansetelling. En av de mest nevnte er sirkelreferanser: Anta at A referanser B, B refererer til C og C refererer til B. Hvis en skulle falle sin referanse til B, vil både B og C har fortsatt en referanse telling på 1, og vil ikke bli slettet med tradisjonell referansetelling. CPython (referansetelling er ikke en del av python seg selv, men en del av den C gjennomføringen av denne) fanger sirkelreferanser med en separat datasanering rutine at det kan kjøres periodisk ...

En annen ulempe: referansetelling kan gjøre utførelse langsommere. Hver gang et objekt er referert og dereferenced, tolken / VM må sjekke for å se om antallet har gått ned til 0 (og deretter allokere hvis det gjorde). Garbage Collection trenger ikke å gjøre dette.

Dessuten kan Søppel Collection gjøres i en separat tråd (selv om det kan være litt vanskelig). På maskiner med mye RAM og for prosesser som bruker minne sakte, kan du ikke ønsker å gjøre GC i det hele tatt! Referansetelling ville være en bit av en ulempe der det gjelder ytelse ...

Svarte 22/08/2008 kl. 09:10
kilden bruker

stemmer
26

Egentlig referere telling og strategier som brukes av Sun JVM er alle forskjellige typer søppelrydding algoritmer.

Det er to brede tilnærminger for å spore opp døde objekter: sporing og referansetelling. I tracing GC starter fra "røtter" - ting som stack referanser, og sporer alle nås (live) stedene. Noe som ikke kan nås anses døde. I referanse telling hver gang er modifisert en referanse til objektet som er involvert har sin teller oppdatert. Enhver gjenstand som referanseantall blir satt til null anses døde.

Med utgangspunktet alle GC implementeringer det er handel offs men sporing er vanligvis god for høy gjennom sette (dvs. rask) drift, men har lengre pause ganger (større hull der brukergrensesnittet eller programmet kan fryse opp). Referansetelling kan operere i mindre biter, men vil bli langsommere samlet. Det kan bety mindre fryser, men dårligere ytelse overall.

I tillegg krever en referansetelle GC en syklus detektor for å rydde opp eventuelle objekter i en syklus som ikke vil bli fanget opp av deres referansetelle alene. Perl 5 har ikke en syklus detektor i sin GC implementering og kan lekke minne som var syklisk.

Forskning har også blitt gjort for å få det beste fra begge verdener (lav pausetider, høy gjennomstrømning): http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/urc-oopsla-2003.pdf

Svarte 13/10/2008 kl. 01:42
kilden bruker

stemmer
13

Darren Thomas gir et godt svar. Men det er en stor forskjell mellom Java og Python tilnærminger som med referansetelling i felles sak (ingen sirkelreferanser) objekter er ryddet opp umiddelbart i stedet for på et ubestemt senere tidspunkt.

For eksempel kan jeg skrive slurvete, ikke-bærbar koden i CPython som

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

og filen descriptor for den filen jeg åpnet vil bli ryddet opp umiddelbart fordi så snart referanse til den åpne filen går bort, er filen søppel samles opp og filen beskrivelse er frigjort. Selvfølgelig, hvis jeg kjører Jython eller Ironpython eller muligens PYPY, da søppelinnsamler vil ikke nødvendigvis kjøre før mye senere; muligens jeg skal gå tom for fildeskriptorer først og mitt program vil krasje.

Så du bør være å skrive kode som ser ut som

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

men noen ganger folk liker å stole på referansetelling alltid frigjøre sine ressurser fordi det kan noen ganger gjøre koden litt kortere.

Jeg vil si at den beste søppelinnsamler er den med best ytelse, som i dag synes å være de Java-stil generasjons søppel samlere som kan kjøres i en egen tråd, og har alle disse sprø optimaliseringer, etc. Forskjellene i hvordan du skrive kode skal være ubetydelig, og ideelt sett ikke-eksisterende.

Svarte 22/08/2008 kl. 12:40
kilden bruker

stemmer
8

Jeg tror artikkelen " Java teori og praksis: En kort historie av garbage collection " fra IBM skal bidra til å forklare noen av spørsmålene du har.

Svarte 22/08/2008 kl. 07:40
kilden bruker

stemmer
5

Søppelrydding er raskere (mer tidseffektiv) enn referansetelling, hvis du har nok minne. For eksempel vil en kopiering gc krysser den "live" objekter og kopierer dem til en ny plass, og kan gjenvinne alle de "døde" gjenstander i ett trinn ved å merke en hel minneområde. Dette er svært effektiv, hvis du har nok minne. Generasjons samlinger bruke kunnskapen om at "de fleste objekter dø ung"; ofte bare noen få prosent av objekter må kopieres.

[Dette er også grunnen til at GC kan være raskere enn malloc / free]

Referansetelling er mye mer plasseffektiv enn søppelrydding, siden det gjenvinner hukommelsen i det øyeblikket det blir ikke nås. Dette er hyggelig når du ønsker å legge finalizers til objekter (for eksempel for å lukke en fil når filen objektet blir ikke nås). En referansetellesystem kan fungere selv når det bare noen få prosent av minnet er fri. Men ledelsen kostnadene ved å måtte øke eller redusere tellere ved hver pekeren oppdraget koster mye tid, og en slags søppelrydding er fortsatt behov for å gjenvinne sykluser.

Så trade-off er klar: Hvis du må jobbe i et minne med begrenset miljø, eller hvis du trenger presise finalizers, bruke referansetelling. Hvis du har nok minne og trenger hastighet, bruke søppelrydding.

Svarte 16/09/2008 kl. 16:38
kilden bruker

stemmer
3

En stor ulempe med Java sporing GC er at fra tid til annen vil det "stop the world" og fryse søknad om en relativt lang tid å gjøre en full GC. Hvis haugen er stor og objektoversikten komplekse, vil det fryse i noen sekunder. Også hver hele GC besøker hele objektet treet igjen og om igjen, noe som er trolig ganske ineffektiv. En annen ulempe av veien Java gjør GC er at du har å fortelle JVM hva haugen størrelsen du ønsker (hvis standard ikke er god nok); JVM stammer fra den aktuelle verdien flere terskler som vil utløse den GC-prosessen når det er for mye søppel samler seg opp i haugen.

Jeg antar at dette er faktisk den viktigste årsaken til jerky følelsen av Android (basert på Java), selv på de dyreste mobiltelefoner, sammenlignet med glatthet av iOS (basert på Objective-C, og ved hjelp av RC).

Jeg vil gjerne se en JVM alternativet for å aktivere RC minnehåndtering, og kanskje holde GC bare å kjøre som en siste utvei når det ikke er mer minne igjen.

Svarte 19/10/2011 kl. 18:40
kilden bruker

stemmer
2

Referansetelling er spesielt vanskelig å gjøre effektivt i et multi-gjenge miljø. Jeg vet ikke hvordan du vil selv begynne å gjøre det uten å komme inn maskinvareassistert transaksjoner eller lignende (for øyeblikket) uvanlige atom instruksjoner.

Referansetelling er enkel å implementere. JVM har hatt mye penger sunket i konkurrerende implementeringer, så det burde ikke være overraskende at de gjennomfører meget gode løsninger på svært vanskelige problemer. Men, er det blitt stadig lettere å målrette din favoritt språket på JVM.

Svarte 05/09/2008 kl. 20:03
kilden bruker

stemmer
2

Den nyeste Sun Java VM faktisk har flere GC algoritmer som du kan justere. Java VM spesifikasjoner med vilje utelatt å spesifisere selve GC atferd for å tillate ulike (og flere) GC algoritmer for ulike VM.

For eksempel, for alle folk som misliker "stop-the-world" tilnærming av standard Sun Java VM GC atferd, er det VM som IBMs WebSphere sanntid som lar sanntid programmet kjøre på Java.

Siden Java VM spec er offentlig tilgjengelig, det er (teoretisk) ingenting stoppe noen fra å implementere en Java VM som bruker CPython er GC algoritme.

Svarte 22/08/2008 kl. 22:58
kilden bruker

stemmer
1

Sent i spillet, men jeg tror en viktig begrunnelse for RC i python er dens enkelhet. Se denne e-posten ved Alex Martelli , for eksempel.

(Jeg kunne ikke finne en link utenfor google cache, e-datoen fra 13 oktober 2005 på python listen).

Svarte 22/10/2009 kl. 01:11
kilden bruker

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