Warum sind Garbage Collectors böse?

Gast #3720425
Lesenswert?

Hallo,
Viele gängige Programmiersprachen (z.B. C#) kümmern sich um eine 
automatische Speicherverwaltung per garbage Collector. Ich finde das 
Konzept super, und auch in der Praxis sehr angenehm.

Trotzdem lese ich hier oft, dass bestimmte Zeitgenossen diese 
Funktionalität verteufeln. Warum eigentlich? Was spricht gegen die 
Verwendung einer automatischen Speicherverwaltung?
#3720433
Lesenswert?

Hobbyist schrieb:
> Trotzdem lese ich hier oft, dass bestimmte Zeitgenossen diese
> Funktionalität verteufeln. Warum eigentlich? Was spricht gegen die
> Verwendung einer automatischen Speicherverwaltung?

Der Anwendungsbereich.

Auf einem Mikrocontroller wuerde sich der Overhead eines GC sehr 
bemerkbar machen.

Das und Generationskonflikte.. ;)
Die alte Laier von "Derjenige der weiss was er macht, braucht das nicht"
Gast #3720435
Lesenswert?

Hobbyist schrieb:
> Trotzdem lese ich hier oft, dass bestimmte Zeitgenossen diese
> Funktionalität verteufeln. Warum eigentlich? Was spricht gegen die
> Verwendung einer automatischen Speicherverwaltung?

Das Verhalten ist nicht vorhersehbar. Und das Letzte, was man bei 
manchen Mikrocontroller-Anwendungen möchte, ist nicht vorhersehbares 
Verhalten. Stell dir vor, bei deinem ABS-System im Auto verzögert sich 
die Bremsensteuerung, weil der zuständige Mikrocontroller gerade damit 
beschäftigt ist den Speicher aufzuräumen statt die notwendigen 
Steuerbefehle zu geben.
Gast #3720441
Lesenswert?

Mladen G. schrieb:
> Auf einem Mikrocontroller wuerde sich der Overhead eines GC sehr
> bemerkbar machen.

Mark 99 schrieb:
> Und das Letzte, was man bei
> manchen Mikrocontroller-Anwendungen möchte, ist nicht vorhersehbares
> Verhalten

Achso, das bezog sich also ausschließlich auf µC-Anwendungen. Klar, da 
verzichtet man besser auf sowas.
Ich hatte jetzt eher Desktop-Anwendungen im Kopf. Da sehe ich kein 
Grund, auf eine automatische Speicherverwaltung zu verzichten.

Danke für die Hinweise!
Gast #3720449
Lesenswert?

Hobbyist schrieb:
> Da sehe ich kein
> Grund, auf eine automatische Speicherverwaltung zu verzichten.

ich schon, es funktioniert einfach nicht 100%.

Fast jede javaanwendung hat ein Speichleck. Je länger sie laufen, desto 
mehr Speicher wird verwendet.

Bei einfachen Objekten mag das ja noch alles gehen, aber sobald 
resourcen verwendet werden (files, Schriftarten, threads), klappt das 
einfach nicht.

Dafür werden dann wie bei C# using verwendet.

Ich finde ein definiertes Verhalten wie bei c++ mit dem Destruktor 
besser.
#3720465
Lesenswert?

Peter II schrieb:
> Fast jede javaanwendung hat ein Speichleck. Je länger sie laufen, desto
> mehr Speicher wird verwendet.

Wenn ich mir das hier so ansehe
http://acadopus.de/java/die-typischen-faelle-von-memory-leaks-in-java-anwendungen_4002.html
dann hängen diese Probleme weniger mit GC zusammen, als mit der recht 
freizügigen Verwendung von Speicher generell, mit Links an sonstundeiner 
Stelle. Die meisten dort beschriebenen Effekte betreffen Speicher, der 
tatsächlich noch referenziert wird, auch wenn die Links vielleicht 
niemand mehr wirklich braucht. Ob das dann per GC oder anders behandelt 
wird ändert nichts am Volumen.
Gast #3720473
Lesenswert?

Mark 99 schrieb:
> Das Verhalten ist nicht vorhersehbar.

Ach, jetzt laßt doch endlich diese Ammenmärchen. Es gibt seit 
Jahrzehnten speziell für den Embedded-Bereich entwickelte GCs, die nicht 
nur berechenbar sind, sondern sogar Echtzeitgarantien geben.

Natürlich kann man nicht den für den PC entwickelten "Standard-"C#-GC 
damit vergleichen.
#3720487
Lesenswert?

Peter II schrieb:
> Fast jede javaanwendung hat ein Speichleck. Je länger sie laufen, desto
> mehr Speicher wird verwendet.
>
> Bei einfachen Objekten mag das ja noch alles gehen, aber sobald
> resourcen verwendet werden (files, Schriftarten, threads), klappt das
> einfach nicht.

Ein GC verhindert nicht alle Speicherlecks, genausowenig wie selber den 
Speicher zu verwalten, nur muss man mit einem GC weniger darauf achten 
wo ich einen String erzeugt habe und wo ich ihn dann aufraeumen muss.

Es ist IMHO schon mal ein Schritt in die richtige Richtung auf 
"nicht-embedded Systemen" einen GC zu verwenden, falls Entwicklungszeit 
eine Rolle spielt.
#3720552
Lesenswert?

dumdi dum schrieb:
> Michael schrieb:
>> Es gibt seit
>> Jahrzehnten speziell für den Embedded-Bereich entwickelte GCs, die nicht
>> nur berechenbar sind, sondern sogar Echtzeitgarantien geben.
>
> einen Namen dazu?

Michael schrieb:
> Ist nicht wirklich mein Gebiet, aber ich weiß, daß Harlequin das hatte.
> Mittlerweile heißen die LispWorks.

Ich kann mir das kaum vorstellen, weil LispWorks eigentlich nicht für 
Embedded Anwendungen gedacht ist. F

Magst Du da nicht mal nachforschen ? Wäre sehr interessant.

Grüße
Andreas
#3720553
Lesenswert?

Peter II schrieb:

> Fast jede javaanwendung hat ein Speichleck. Je länger sie laufen, desto
> mehr Speicher wird verwendet.

Ich hab eine ähnliche Erfahrung mit einem C# Programm gemacht, in deren 
Weiterentwicklung ich vor Jahren mal eine Zeit lang involviert war.

Es war eigentlich keine großartige Sache, trotzdem präsentierte sich das 
System so, dass man beim Hochfahren der Applikation im Taskmanager 
zusehen konnte, wie die MB in die Höhe kletterten. Nach einigen Stunden 
gab die Applikation dann mit einem 'Out of Memory' auf.
Wie gesagt, war keine großartige Sache, ein paar dynamische Listen, in 
die immer wieder mal Einträge dazu kamen, aber auch im Zuge der 
Abarbeitung wieder wegkamen. Das waren Störungsmeldungen von 
Gebäudemanagment-Steuerungen, die gesammelt, klassifiziert und je nach 
Situation an diverse Abnehmer verteilt wurden. Mit C++, 
Standardcontainern und den RAII Konzept keine großartige Sache in der 
Speicherverwaltung, aber in C# kam es da wohl zu irgendwelchen 
gegenseitigen Blockaden, so dass der GC den Speicher nicht mehr 
vollständig aufgeräumt hat. Jedenfalls hat das Suchen nach den Ursachen 
einiges an Zeit verschlungen (hab nicht ich gemacht). Mehr Zeit als ein 
ganz einfacher RAII Ansatz in C++ gekostet hätte.

> Das und Generationskonflikte.. ;)
> Die alte Laier von "Derjenige der weiss was er macht, braucht das nicht"

Da hast du nicht ganz unrecht.
Für meinen Teil kann ich sagen: Ich vermisse einen GC nicht und komm 
auch ohne ganz gut zurecht.
#3720573
Lesenswert?

Karl Heinz schrieb:
> Jedenfalls hat das Suchen nach den Ursachen
> einiges an Zeit verschlungen (hab nicht ich gemacht). Mehr Zeit als ein
> ganz einfacher RAII Ansatz in C++ gekostet hätte.

Wenn ich mit einem Hammer schneller bin als mit einer Nagelpistole, 
liegt das Problem sehr wahrscheinlich nicht an der Nagelpistole, sondern 
daran wie ich sie nutze ;)

Mna kann alles falsch bedienen, d.h. aber nicht, dass das Werkzeug 
fehlerhaft ist.
#3720580
Lesenswert?

Mladen G. schrieb:
> Karl Heinz schrieb:
>> Jedenfalls hat das Suchen nach den Ursachen
>> einiges an Zeit verschlungen (hab nicht ich gemacht). Mehr Zeit als ein
>> ganz einfacher RAII Ansatz in C++ gekostet hätte.
>
> Wenn ich mit einem Hammer schneller bin als mit einer Nagelpistole,
> liegt das Problem sehr wahrscheinlich nicht an der Nagelpistole, sondern
> daran wie ich sie nutze ;)
>
> Mna kann alles falsch bedienen, d.h. aber nicht, dass das Werkzeug
> fehlerhaft ist.

Da stimme ich dir durchaus zu.
Wenn allerdings das Werkzeug 'Nagelpistole' als das Beste seit 
geschnittenem Brot beworben wird und sich dann ganz offensichtlich in 
der Praxis rausstellt, das nicht alles Gold ist was glänzt und es einem 
nicht davon entbindet mitzudenken und aufzupassen (was aber keiner 
wahrhaben will), dann komm ich auch mit meinem bewährten Werkzeug 
'Hammer' durchaus klar und benutzte den lieber. Vor allen Dingen dann, 
wenn der Hammer mir dann auch noch einen Nagelauszieher mitliefert, den 
ich mit einer Nagelpistole nicht habe (ich spiele damit auf Destruktoren 
an, die in C++ zuverlässig zum Aufräumen benutzt werden können, 
zumindest in C# jedoch völlig nutzlos sind)

> Das und Generationskonflikte.. ;)
> Die alte Laier von "Derjenige der weiss was er macht, braucht das nicht"
Da hast du nicht ganz unrecht.
Für meinen Teil kann ich sagen: Ich vermisse einen GC nicht und komm 
auch ohne ganz gut zurecht.
Gast #3720583
Lesenswert?

Mladen G. schrieb:
> Mna kann alles falsch bedienen, d.h. aber nicht, dass das Werkzeug
> fehlerhaft ist.

wenn bei dem Werkzeug aber nicht offensichtlich ist wie man es bedienen 
soll, das ist das Werkzeug daran schuld.

Ist wie bei einen Fernseher, wenn ich erst in der Doku nachlesen muss 
wie ich ihn einschalten kann, das ist nicht praxistauglich.
#3720586
Lesenswert?

Karl Heinz schrieb:
> Für meinen Teil kann ich sagen: Ich vermisse einen GC nicht und komm
> auch ohne ganz gut zurecht.

Hat alles seine Vor- und Nachteile. GCs kamen auf, weil die 
Speicherverwaltung von C/C++ den Leuten über den Kopf wuchs. Mit 
Programmen, die auch sehr gerne Lecks hatten oder Speicher doppelt 
freigaben.

Ist das Ei des Kolumbus mittlerweile erfunden?
#3720590
Lesenswert?

Karl Heinz schrieb:
>> Das und Generationskonflikte.. ;)
>> Die alte Laier von "Derjenige der weiss was er macht, braucht das nicht"
> Da hast du nicht ganz unrecht.
> Für meinen Teil kann ich sagen: Ich vermisse einen GC nicht und komm
> auch ohne ganz gut zurecht.

Ich sage mal so, mit GC suche ich jetzt zumindest nicht mehr die 
Speicherleaks anderer :-), und entgegen Peter II's Aussagen, laufen bei 
uns sogar in Java programmierte Mutithreaded Server in 
Finanzanwendungen, die wochenlang nicht runtergefahren werden.

Und ein Destruktor nützt halt nichts, wenn er nicht aufgerufen wird. 
Genausowenig wie ein GC was freigeben kann, wenn das Programm es noch 
benutzt, bzw Referenzen davon nicht freigegeben werden.

Karl Heinz schrieb:
> Wenn allerdings das Werkzeug 'Nagelpistole' als das Beste seit
> geschnittenem Brot beworben wird und sich dann ganz offensichtlich in
> der Praxis rausstellt, das nicht alles Gold ist was glänzt und es einem
> nicht davon entbindet mitzudenken und aufzupassen, dann komm ich auch
> mit meinem bewährten Werkzeug 'Hammer' durchaus klar.

Da stimme ich völlig zu.
#3720592
Lesenswert?

Karl Heinz schrieb:
> Da stimme ich dir durchaus zu.
> Wenn allerdings das Werkzeug 'Nagelpistole' als das Beste seit
> geschnittenem Brot beworben wird und sich dann ganz offensichtlich in
> der Praxis rausstellt, das nicht alles Gold ist was glänzt und es einem
> nicht davon entbindet mitzudenken und aufzupassen (was aber keiner
> wahrhaben will), dann komm ich auch mit meinem bewährten Werkzeug
> 'Hammer' durchaus klar.

Naja, Marketing hat auch immer Einfluss.. Java war die Sprache die vom 
Marketing als Sprache beworben wurde, die keine Zeiger hat, und damit 
viele Probleme vermeidet.
Woher kommen denn dann diese NullPointerExceptions? ;)

Da haben die Entwickler nicht schnell genuig mit dem Marketinggefasel 
mitgehalten und sind nichtmehr dazu gekommen es in 
"NullReferenceException" umzubennen.

Selbst mit GC kann man immer noch Speicherlecks haben.

Karl Heinz schrieb:
>> Das und Generationskonflikte.. ;)
>> Die alte Laier von "Derjenige der weiss was er macht, braucht das nicht"
> Da hast du nicht ganz unrecht.
> Für meinen Teil kann ich sagen: Ich vermisse einen GC nicht und komm
> auch ohne ganz gut zurecht.

Ach, das geht ja nicht erst beim GC los.
Habe bei einem fruehren AG in der Kantine oefters Diskussionen ala "Wozu 
eigentlich OO und C++? Ging doch auch alles mit C und prodzedural. 
Diejenigen die wissen was sie machen, brauchen das nicht."

Diese Diskussionen gab es schon vor 30 Jahren, damals ging es allerdings 
um Assembler vs C, "Wozu eigentlich Hochsprachen? Diejenigen die wissen 
was sie machen, koennen das in Assembler viel besser.."

Ich bin Java Entwickler seit ueber 14 Jahren, arbeite seit 12 Jahren mit 
Eclipse, mich bringt keiner dazu zu IntellJ zu wechseln :D
Gast #3720598
Lesenswert?

Udo Schmitt schrieb:
> Ist aber gerade bei Java jetzt nicht wirklich der Fall. Der funktioniert
> automatisch und seit spätestens 1.5 ziemlich gut.

leider nicht. Wir haben bei uns einige Tomcat Anwendungen, und diese 
müssen einmal in der Woche neu gestartet werden, sonst müsste man 
Unmengen an Speicher in den Server stecken.
Gast #3720603
Lesenswert?

Peter II schrieb:
> leider nicht. Wir haben bei uns einige Tomcat Anwendungen, und diese
> müssen einmal in der Woche neu gestartet werden, sonst müsste man
> Unmengen an Speicher in den Server stecken.

Der GC hilft natürlich nur, wenn man Referenzen auf Speicher auch 
irgendwann mal wieder aufgibt.

Oder wie stellst du dir das vor?

"Super, meine dreißig Gigabyte Daten kann ich wunderbar in den RAM 
einlesen. Mein hochoptimierter GC behält immer nur die letzten zwei 
Gigabyte und wirft den Rest weg." ;-)
Gast #3720612
Lesenswert?

Michael schrieb:
> Der GC hilft natürlich nur, wenn man Referenzen auf Speicher auch
> irgendwann mal wieder aufgibt.

die Frage ist wie man es schafft immer die Referenz freizugeben.

z.b. eine Verkette Liste wo das Ende auf den Anfang zeigt.

Wann räumt der GC das nun auf?

Noch schlimmer ist wenn man mit sehr großen Datenmengen arbeitet, dann 
hilft es auch nicht die Referenz zu löschen. Dann muss man den GC 
teilweise von Hand aufrufen, damit man den Speicher gleich wieder 
verwenden kann, weil der GC sonst erst später aufräumen will.

Bei C(C++) muss ich ihn zwar von Hand freigeben, weiß aber das er dann 
auch wirklich frei ist.
Persönliche Seite #3720616
Lesenswert?

Peter II schrieb:
> leider nicht. Wir haben bei uns einige Tomcat Anwendungen, und diese
> müssen einmal in der Woche neu gestartet werden, sonst müsste man
> Unmengen an Speicher in den Server stecken.

Bei sowas gibt es ja zwei Möglichkeiten:
- Auf den bösen GC schimpfen der ja nix kann
- Mal mit einem passendem Tool (z.B. JProfiler) sich mal ansehen welche 
Objekte da immer mehr Speicher verbrauchen und den Bug fixen

Peter II schrieb:
> Noch schlimmer ist wenn man mit sehr großen Datenmengen arbeitet, dann
> hilft es auch nicht die Referenz zu löschen. Dann muss man den GC
> teilweise von Hand aufrufen

NEEEIN! Bitte nicht, das ist erstens Unnötig und Verschlechtert zweitens 
die Performance und ist drittens nicht garantiert da überhaupt etwas 
passiert...
#3720629
Lesenswert?

Michael schrieb:
> Komisch. Irre ich mich mit Harlequin? Oder haben die das aufgegeben?

ALso bei Harlequin bin ich mir nicht sicher. Aber bei LispWorks ist mir 
nie aufgefallen, dass die auch Embedded Versionen haben.
Vielleicht hat Dave das bei der Übernahme rausgeworfen ?

Der GC der Windows Version war aber schon nice.

Mladen G. schrieb:
> Das und Generationskonflikte.. ;)
> Die alte Laier von "Derjenige der weiss was er macht, braucht das nicht"

Appropos:
Der LispWorks GC ist ein Generational-GC und macht (meist) keine 
Probleme.

Aber falls Du die Generation der Hacker meintest:
GCs wurden schon in Sprachen eingesetzt (z.B. Lisp, Smalltalk) als die 
einzige Anwendung von Java noch "mahlen und mit heissem Wasser 
aufkochen" war.

Von daher ist das für diese (Hacker-)Generation eher kalter Kaffee ;-)

Grüße
Andreas
#3720632
Lesenswert?

Peter II schrieb:
> z.b. eine Verkette Liste wo das Ende auf den Anfang zeigt.
> Wann räumt der GC das nun auf?

Im Gegensatz zu Referenzzählern können GCs damit problemlos umgehen. 
Wenn die beispielsweise ausgehend von einem Wurzelobjekt Links nur in 
Objekten berücksichtigen, die sie bereits kennen. Tote Strukturen, die 
nur auf sich selbst verweisen, fallen dabei automatisch raus.
#3720642
Lesenswert?

Peter II schrieb:
> die Frage ist wie man es schafft immer die Referenz freizugeben.
>
> z.b. eine Verkette Liste wo das Ende auf den Anfang zeigt.
>
> Wann räumt der GC das nun auf?

Er räumt immerhin auf, ohne musst du alles aufräumen indem du es von 
Hand freigibst. Solange die Werte benutzt werden und in der Liste sind 
kann der GC natürlich nichts freigeben, solange kannst du Objekte auch 
nicht in C++ oder C freigeben

Peter II schrieb:
> Noch schlimmer ist wenn man mit sehr großen Datenmengen arbeitet, dann
> hilft es auch nicht die Referenz zu löschen. Dann muss man den GC
> teilweise von Hand aufrufen, damit man den Speicher gleich wieder
> verwenden kann, weil der GC sonst erst später aufräumen will.

Er räumt spätestens dann auf, wenn er Speicherprobleme bekommt. Und ja 
man kann ihn auch manuell aufrufen wenn man weiß jetzt habe ich eh etwas 
Zeit...

Peter II schrieb:
> Bei C(C++) muss ich ihn zwar von Hand freigeben, weiß aber das er dann
> auch wirklich frei ist.
Du kannst in Java bei komplexeren Strukturen Pointer explizit nullen und 
so dem GC das Leben einfacher machen, aber es funktioniert auch 
erstaunlich gut ohne.

Wir benutzen Java auch um XML Dateien, die mehrere GByte groß sind zu 
parsen, mit Daten aus einer Datenbank einen Vollabgleich zu fahren und 
ggf in die Datenbank zu speichern. Da werden viele GByte an Speicher 
alloziert und wieder weggeworfen, alles ohne Probleme und ohne manuelle 
Nachhilfe, es geht also.

Und das Schönste: Es geht mit einer Lib auf Sun, Aix, allen Linux 
Derivaten, Windows.
Und auf allen diesen Systemen mit DB/2, Oracle und MS-SQL ohne daß ich 
eine Zeile spezifischen Code schreiben musste und ohne daß wir für jede 
Betriebssystem/Datenbank Kombination eine extra Auslieferungsversion 
compilieren/linken, archivieren und nicht zuletzt testen müssen!
#3720644
Lesenswert?

Peter II schrieb:
> so einfach ist das glaube ich nicht. Dann würde der GC ein Threadobjekt
> auch wegschmeißen.

Nein, denn irgendwo gibts garantiert eine Liste aller Threads. Und diese 
Liste wiederum irgendwo anders, und ... und irgendwann bist du an der 
Wurzel. So jedenfalls läuft das in jenen Sprachen, wo GC herkommt, wie 
Lisp oder Smalltalk.

Es entbehrt nicht einer gewissen Komik, ausgerechnet das klassischste 
aller Beispiele für GC und gegen Referenzzähler gegen GC in Stellung 
bringen zu wollen.
#3720646
Lesenswert?

dumdi dum schrieb:
> Michael schrieb:
>> Es gibt seit
>> Jahrzehnten speziell für den Embedded-Bereich entwickelte GCs, die nicht
>> nur berechenbar sind, sondern sogar Echtzeitgarantien geben.
>
> einen Namen dazu?

MetronomeGC, JamaicaVM/GC etc.

http://researcher.watson.ibm.com/researcher/view_group_subpage.php?id=175
https://www.aicas.com/cms/en/publication-details/351
http://reports-archive.adm.cs.cmu.edu/anon/2001/abstracts/01-174.html
http://dl.acm.org/citation.cfm?id=2602996

Perfekt, im Sinne von: erreichen den selben geringen Overhead wie 
manuelle Speicherverwaltung, sind die aber alle nicht.
Ebenso ist eine manuelle Speicherverwaltung nicht perfekt. Stichworte 
u.a.: Heap fragmentation, heap compaction
#3720647
Lesenswert?

Peter II schrieb:

> z.b. eine Verkette Liste wo das Ende auf den Anfang zeigt.
>
> Wann räumt der GC das nun auf?

Du meinst bei Objekten die auf sich selbst referenzieren? Na das wird 
aufgeräumt wenn der GC läuft. Such einmal nach "Tracing garbage 
collectors". Nur die billigsten GCs sollten darauf hineinfallen.

> Noch schlimmer ist wenn man mit sehr großen Datenmengen arbeitet, dann
> hilft es auch nicht die Referenz zu löschen. Dann muss man den GC
> teilweise von Hand aufrufen, damit man den Speicher gleich wieder
> verwenden kann, weil der GC sonst erst später aufräumen will.

Das ist wohl ein spezieller Spezialfall und wenn das wirklich der Fall 
ist, dann ist auch manueller GC-Aufruf kein Beinbruch. Im Normalfall ist 
das Environment aber so intelligent selbst zu merken, dass es jetzt 
aufräumen muss. Ich habe zumindest noch nie einen manuellen Aufruf 
benötigt.

> Bei C(C++) muss ich ihn zwar von Hand freigeben, weiß aber das er dann
> auch wirklich frei ist.

Was dir nicht viel bringt außer eventuell ein gutes Gewissen.
#3720656
Lesenswert?

Peter II schrieb:
> z.b. eine Verkette Liste wo das Ende auf den Anfang zeigt.
>
> Wann räumt der GC das nun auf?

Wenn er Zeit dazu hat ;) Normalerweise ist das kein Problem so was 
aufzuräumen/freizugeben. Der GC sucht bspw. von sogenannten GC roots 
(lokalen Variablen, statischen Variablen etc.) ausgehend auf was diese 
verweisen. Alles was nicht erreicht werden kann, kann freigegeben 
werden.

> Bei C(C++) muss ich ihn zwar von Hand freigeben, weiß aber das er dann
> auch wirklich frei ist.

Frei schon, aber nicht zwingend nutzbar (Fragmentierung...)
#3720657
Lesenswert?

Peter II schrieb:
> Warum wird ein Filehandle nicht vom GC aufgeräumt wenn keine Referenz
> mehr da ist? Die Datei bleibt ewig geöffnet.

Die überschreitest damit die Grenze von Anwenderprogramm und 
Betriebssystem. GC gilt nicht systemweit, sondern ist auf die 
Anwendungsebene des Prozesses begrenzt. Filehandles als API-Elements 
eines Betriebssystems sind somit nicht automatisch Teil eines GC 
Mechanimusses des Anwenderprogramms.

Wenn man in der betreffenden Sprache einen Wrapper um das Handle baut, 
um ein Sprachobjekt daraus zu zimmern, dann kann man diesem Wrapper eine 
Aufräum-Methode verpassen, die spätestens mit Freigabe des Wrappers im 
GC das Handle schliesst. So das gewollt ist.
#3720658
Lesenswert?

Peter II schrieb:

> die Frage ist wie man es schafft immer die Referenz freizugeben.
>
> z.b. eine Verkette Liste wo das Ende auf den Anfang zeigt.

Da gibt es die verschiedensten Ansätzte (mark & sweep und wie die alle 
heissen). Das ist für einen modernen GC nun kein Problem.

Voraussetzung dafür ist aber, dass es ausserhalb der Kette keine 
Referenz mehr auf irgend ein Element der Kette gibt. Das liegt dann aber 
in der Verantwortung des Entwicklers.

Die Ursache in Memory Leaks kommen häufig daher, dass mit Frameworks 
gearbeitet wird, die von den Entwicklern zuwenig genau verstanden werden 
(z.B. liefert ein getElement() nun eine Refernz oder eine Kopie? 
Speichert ein putElement() eine Referenz oder eine Kopie?).

> Wann räumt der GC das nun auf?

Das ist ein sehr heikler Punkt. Auch hier gibt es verschiedenste 
Strategien (wenn der Speicher zu 90% aufgebraucht ist, nach x ms, nach x 
Maus-Events, etc.). Ein anderer interessanten Punkt ist, ob immer 
vollständig aufgeräumt wird (kann lange dauern) oder nur eine maximale 
Zeit lang (ist sehr viel komplexer).

==> GC an sich funktioniert heute sehr gut und kann auch sehr gut auf 
die Rahmenbedingungen ausgerichtet werden. Es schützt aber nicht davor, 
dass ein schlechter Entwickler schlechte Software schreibt.

Gruss
Claude

PS: Ich kenne komplexe Server-Applikationen, mit denen rund um die Uhr 
sehr viele Leute arbeiten, die monatelang nicht herunter gefahren 
werden.
Moderator #3720661
Lesenswert?

Nachdem ich es auf meinem ersten Computer geschafft habe, ein
Basic-Programm immer wieder für jeweils ca. 2s in der GC verharren
zu lassen, war für mich GC auch böse :)

Mittlerweile, auf moderneren Computern mit moderneren
Programmiersprachen und Laufzeitsystemen, machen sich die von der GC
verursachten Unregelmäßigkeiten im Programmablauf kaum noch bemerkbar.
Deswegen mag ich für die High-Level-Programmierung ganz gerne auch
wieder Sprachen mit GC.

Man muss sich aber eben bewusst sein, dass GC zwar ungültige Pointer und
mehrfache Freigaben perfekt verhindert, nicht aber Speicherlecks. Die
Verhinderung von Speicherlecks wird zwar von der GC bis zu einem
gewissen Grad unterstützt, bleibt aber ohne Mitdenken des Programmierers
erfolglos. In dem von A. K. verlinkten Artikel

  http://acadopus.de/java/die-typischen-faelle-von-memory-leaks-in-java-anwendungen_4002.html

gibt es schöne Beispiele dafür.

Das nach wie vor bestehende Problem der GC: Um Speicherlecks zu
vermeiden, muss der Programmierer ziemlich genau wissen, wie
Bibliotheksfunktionen den Speicher nutzen und wo möglicherweise
versteckte Referenzen auf Objekte gehalten werden. Bei den immer größer
werdenden Laufzeit- und anderen Bibliotheksfunktionen ist es aber nahezu
unmöglich, diesbezüglich den erforderlichen Überblick zu behalten.

Bei den klassichen auf malloc() und free() basierenden Systemen ist das
vergleichsweise einfach: Normalerweise gibt diejenige Programmeinheit,
die Speicher anfordert, diesen auch wieder zurück. Ist dies nicht
möglich (bspw. wenn eine Funktion ein dynamisch angelegtes Objekt an den
Aufrufer zurückgibt), dann ist dies in der Dokumentation vermerkt
zusammen mit Hinweisen, wann und wie der Speicher wieder freigegeben
werden soll. Das funktioniert aber natürlich auch nur dann, wenn die
Dokumentation entsprechend vollständig ist und vom Programmierer auch
gelesen wird. In beide Bereichen gibt es noch Defizite.
#3720662
Lesenswert?

Peter II schrieb:

> ist nicht von uns die Anwendung, also kein Quelltext vorhanden. Damit
> bringt es auch wenig wenn ich den Fehler finden würde.

Das ist aber jetzt schon ganz hart am Getrolle. Da hat jemand ein 
Memory-Leak fabriziert und daher ist der GC schuld und unnötig. Als ob 
der Programmierer in C++ nicht noch ein viel größeres Memory-Leak 
produziert hätte.
Das Einzige was man dem GC hier vorwerfen kann ist, dass der 
Programmierer die Anwendung in C++ ev. gar nicht stabil bekommen hätte 
und daher ein fähigerer Programmierer oder mehr Zeit notwendig gewesen 
wären.
Gast #3720668
Lesenswert?

Läubi .. schrieb:
> NEEEIN! Bitte nicht, das ist erstens Unnötig und Verschlechtert zweitens
> die Performance und ist drittens nicht garantiert da überhaupt etwas
> passiert...

Ja leider ist das manchmal halt leider nicht vermeidbar. Ich kenn das 
von C# wenn man mit großen Arrays arbeitet und zb 1000MB freigibt und 
gleich in der nächsten Instruktion 1500MB allokiert. Ohne manuelles 
Aufrufen von GC.Collect(), wurde der Speicher nicht schnell genug 
freigegeben und führte zwangsläufig zu einer Out-Of-Memory Exception auf 
meinem Rechner. Auch wenn man die Referenzen auf NULL setzt, in solchen 
Fällen räumt die GC oft nicht schnell genug auf.

Mittlerweile schreibe ich speicherintensive Programme aber ohnehin 
lieber wieder in C++. Das macht auch wieder mehr Spaß wenn man am Ende 
bis aufs letzte optimiert.
#3720674
Lesenswert?

Yalu X. schrieb:
> Bei den klassichen auf malloc() und free() basierenden Systemen ist das
> vergleichsweise einfach: Normalerweise gibt diejenige Programmeinheit,
> die Speicher anfordert, diesen auch wieder zurück.

Das führt freilich zum umgekehrten Extrem. Wenn Code von Modul A einen 
Link auf ein Objekt von Modul B speichert, ohne dass der Programmierer 
das weiss, dann gibts bei GC ein scheinbares Speicherleck - wie im Link 
beschrieben - und bei malloc/free einen Sprung ins Nichts. Such es dir 
aus. ;-)
Gast #3720677
Lesenswert?

Jan Hansen schrieb:
> Das ist aber jetzt schon ganz hart am Getrolle. Da hat jemand ein
> Memory-Leak fabriziert und daher ist der GC schuld und unnötig

wo habe ich geschrieben das der GC daran schuld ist? Mir ist nur 
aufgefallen das wachsender Speicherverbrauch häufig bei Java auftritt. 
Ob das nun am GC liegt oder nicht kann ich nicht sagen.

Arc Net schrieb:
> Der GC sucht bspw. von sogenannten GC roots
> (lokalen Variablen, statischen Variablen etc.) ausgehend auf was diese
> verweisen.

es werden also ständig versucht alle Objekte zu Prüfen ob sie 
weggeschmissen werden können - kein Wunder warum Java Programm so 
langsam sind
(Kommentar nicht 100% erst gemeint, gibt es werte wie viel CPU zeit der 
GC alleine braucht? )
#3720682
Lesenswert?

Peter II schrieb:
> es werden also ständig versucht alle Objekte zu Prüfen ob sie
> weggeschmissen werden können - kein Wunder warum Java Programm so
> langsam sind

Ja, das ist ein Nebeneffekt. GC benötigt auch temporären Speicher. Die 
Alternativen haben freilich auch Nebeneffekte. So entsteht 
beispielsweise durch Referenzzähler ebenfalls Zusatzaufwand, in Platz 
und Zeit, aber anders verteilt.
#3720688
Lesenswert?

Peter II schrieb:
> (Kommentar nicht 100% erst gemeint, gibt es werte wie viel CPU zeit der
> GC alleine braucht? )

Lässt sich nicht verallgemeinern, weil es die eine GC-Methode nicht 
gibt, ebenso wenig wie das eine für alle anderen typische Programm. 
Für Beispiele siehe wie oben schon genannt:
http://www.anandtech.com/show/8231/a-closer-look-at-android-runtime-art-in-android-l/2
Gast #3720694
Lesenswert?

Hi,

Hobbyist schrieb:
> Achso, das bezog sich also ausschließlich auf µC-Anwendungen.

Nein, das bezieht sich auf so ziemlich alle zeitkritischen Anwendungen. 
Wir stellen eine Echtzeit-Betrugserkennung bei Kreditkartenzahlungen 
her; dabei ist die Garbage Collection ein Dauerthema.

Liebe Grüße,
Karl
Gast #3720700
Lesenswert?

Karl Käfer schrieb:
> Nein, das bezieht sich auf so ziemlich alle zeitkritischen Anwendungen.

Der GC lässt sich ja auch manuell steuern. In zeitkritischen 
Codeabschnitten kann er auch deaktiviert werden.

Zudem läuft der GC ja üblicherweise nebenläufig, so dass die anderen 
Threads davon nichts mitbekommen (es sei denn man hat nur einen Kern 
;-))
#3720704
Lesenswert?

Karl Käfer schrieb:
> Nein, das bezieht sich auf so ziemlich alle zeitkritischen Anwendungen.
> Wir stellen eine Echtzeit-Betrugserkennung bei Kreditkartenzahlungen
> her; dabei ist die Garbage Collection ein Dauerthema.

Wir machen hier etwas sehr aehnliches, der GC ist aber nicht unser 
Problem, sondern die Queries die von Hibernate generiert werden und 
damit die Oracle DB so langsam machen dass die sich nicht mehr vor dem 
Timeout meldet.

Parallelen GC anwerfen sollte zumindest nicht die ganze VM einfrieren 
bei einem GC run.
#3720709
Lesenswert?

Hobbyist schrieb:
> Zudem läuft der GC ja üblicherweise nebenläufig, so dass die anderen
> Threads davon nichts mitbekommen (es sei denn man hat nur einen Kern

Es ist nicht ganz so einfach, eine GC so zu bauen, dass sie ohne 
grössere Aufwirkungen auf andere Threads bleibt. Der Link zur Davik/ART 
Migration erwähnt auch diese Problematik. So wird darin die 
GC-Implementierung von Dalvik als einer der Gründe für Ruckler in 
Android gesehen.
#3720715
Lesenswert?

Peter II schrieb:
> es werden also ständig versucht alle Objekte zu Prüfen ob sie
> weggeschmissen werden können - kein Wunder warum Java Programm so
> langsam sind
> (Kommentar nicht 100% erst gemeint, gibt es werte wie viel CPU zeit der
> GC alleine braucht? )

Wie schon geschrieben wurde, kommt es auf die konkrete Implementierung 
des GCs an z.B. Mark&Sweep
http://en.wikipedia.org/wiki/Mark_and_sweep

In den Links oben zu Echtzeit-GCs sollte sich auch einiges finden 
lassen.
Interessante Ansätze für Echtzeit-GCs auf FPGAs z.B.:
Parallel Real-time Garbage Collection of Multiple Heaps in 
Reconfigurable Hardware, Bacon, Cheng, Shukla, 2014
http://dl.acm.org/citation.cfm?id=2602996
Gast #3720724
Lesenswert?

A. K. schrieb:
> Karl Heinz schrieb:
>> Für meinen Teil kann ich sagen: Ich vermisse einen GC nicht und komm
>> auch ohne ganz gut zurecht.
>
> Hat alles seine Vor- und Nachteile. GCs kamen auf, weil die
> Speicherverwaltung von C/C++ den Leuten über den Kopf wuchs.

Ja, genau. Und denselben Leuten wächst jetzt statt der 
Speicherverwaltung eben der Garbage Collector über den Kopf. Das kann 
man als Fortschritt ansehen, muß man aber nicht.

Garbage Collection ist eine prima Sache, um die Entwicklerproduktivität 
zu steigern. Dafür handelt man sich bei bestimmten Anwendungsfällen eben 
neue Probleme ein.

Liebe Grüße,
Karl
Moderator #3720734
Lesenswert?

A. K. schrieb:
> Das führt freilich zum umgekehrten Extrem. Wenn Code von Modul A einen
> Link auf ein Objekt von Modul B speichert, ohne dass der Programmierer
> das weiss, dann gibts bei GC ein scheinbares Speicherleck - wie im Link
> beschrieben - und bei malloc/free einen Sprung ins Nichts. Such es dir
> aus. ;-)

Ja, hast recht, das kann natürlich auch passieren.

Vielleicht sollten wir einfach wieder zu den klassichen statischen
Sprachen wie Fortran≤77 zurückkehren. Fortran war damals so statisch,
dass man nicht einmal einen Stack brauchte. Und bei den heutzutage
typischen 16GiB Hauptspeicher kann man alle Arrays so groß
dimensionieren, dass ihre Grenzen erst erreicht werden, wenn ein
GC-basiertes Programm schon lange auf Grund von Speicherlecks mit einer
"memory full"-Exception ausgestiegen wäre ;-)
#3720765
Lesenswert?

dumdi dum schrieb:
> Arc Net schrieb:
>> benso ist eine manuelle Speicherverwaltung nicht perfekt. Stichworte
>> u.a.: Heap fragmentation,
>
> Haben GCs nicht auch dieses Problem?

Wenn sie keine Heap Compaction machen, ja. Bspw. gibt es im aktuellen 
.NET-GC einen Schalter mit dem im LOH (Large Object Heap) eine 
Defragmentierung bei Bedarf erzwungen werden kann, Standardeinstellung 
ist, dass dort keine durchgeführt wird. Im SOH (Small Object Heap) wird 
es dagegen automatisch gemacht.
#3720767
Lesenswert?

Peter II schrieb:
> es werden also ständig versucht alle Objekte zu Prüfen ob sie
> weggeschmissen werden können - kein Wunder warum Java Programm so
> langsam sind

Erstens nicht ständig, sondern nur dann wenn der GC läuft.
Und auch da werden bei intelligenten Implementierungen nicht immer alle 
Objekte geprüft. Da gibt es z.B. generationenbasierte Implementierungen. 
Viele Objekte leben nämlich nur ganz kurz (z.B. in einer Schleife) - die 
werden immer berücksichtigt. Lebt ein Objekt länger so wandert es 
irgendwann in die nächste Generation und wird nur noch selten geprüft. 
Es gibt nämlich nur wenige Objekte die eine mittlere Lebensdauer haben. 
Wenn ein Objekt eine gewisse Lebensdauer erreicht hat, dann ist die 
Wahrscheinlichkeit recht groß, dass es noch länger lebt.
Gast #3731181
Lesenswert?

Imho sollte man zwischen "Memory Leak" und "vergessenes Objekt" 
unterscheiden.

Afaik sind memory leaks Speicherbereiche, die vom user/programm nicht 
mehr verwendet werden können, D.h. der Speicher ist echt verloren (ich 
adressiere hier komplexere Systeme, die noch ein OS untendrunter haben).

Bei vielen bisher geschilderten Problemen von OO-Sprachen mit GC geht es 
aber primär um erhöhten Speicherverbrauch von Objekten, die noch 
existieren und auch noch verwendet werden könnten, aber der Programmier 
hat sie aus Schlampigkeit einfach vergessen.
Die andere Variante sind Systemressourcen unterhalb der VM, die vom GC 
nicht erfasst werden und nicht geschlossen/abgebaut werden. Das können 
aus dieser Sicht 'echte' Leaks sein, allerdings halt ohne GC-Kontext, 
die VMs sind meistens in Sprachen ohne GC geschrieben.


Den meisten in 
http://acadopus.de/java/die-typischen-faelle-von-memory-leaks-in-java-anwendungen_4002.html 
genannten "Leaks" kann man durch einfache systematische Suche oder 
Profilern auf die Schliche kommen.
Das gestaltet sich allerdings erheblich einfacher als die Suche nach 
'echten' Leaks, weil ich systembedingt mehr Meta-Informationen zum 
Speicher habe.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren