Forum: PC-Programmierung Warum sind Garbage Collectors böse?


von Hobbyist (Gast)


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?

von Mladen G. (mgira)


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"

von Mark 99 (Gast)


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.

von Hobbyist (Gast)


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!

von Peter II (Gast)


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.

von Frank M. (frank_m35)


Lesenswert?

In dem Artikel über Android und der neuen VM ART wird ein wenig auf die 
Vor- und Nachteile eingegangen und die Schwierigkeiten einen guten 
Garbage Collector zu bauen.
http://www.anandtech.com/show/8231/a-closer-look-at-android-runtime-art-in-android-l/2

von (prx) A. K. (prx)


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.

: Bearbeitet durch User
von Michael (Gast)


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.

von Michael (Gast)


Lesenswert?

Peter II schrieb:
> ich schon, es funktioniert einfach nicht 100%.

Komisch, dann solltest du einfach mal einen GC verwenden, der nicht 
buggy ist.

(Und natürlich eine passende Sprache, bei C hast du immer 
Einschränkungen mit den dort möglichen konservativen GCs)

von Mladen G. (mgira)


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.

von Dumdi D. (dumdidum)


Lesenswert?

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?

von Michael (Gast)


Lesenswert?

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

von Purzel H. (hacky)


Lesenswert?

Ich verzichte auf Controllern generell auf dynamischen Speicher. Waer 
bloed wenn's grad keinen mehr hat, oder nur zerstueckelt

: Bearbeitet durch User
von Andreas H. (ahz)


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

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Mladen G. (mgira)


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.

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Peter II (Gast)


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.

von (prx) A. K. (prx)


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?

: Bearbeitet durch User
von Udo S. (urschmitt)


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.

von Mladen G. (mgira)


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

: Bearbeitet durch User
von Udo S. (urschmitt)


Lesenswert?

Peter II schrieb:
> wenn bei dem Werkzeug aber nicht offensichtlich ist wie man es bedienen
> soll, das ist das Werkzeug daran schuld.

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

von Peter II (Gast)


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.

von Michael (Gast)


Lesenswert?

Andreas H. schrieb:
> Magst Du da nicht mal nachforschen ? Wäre sehr interessant.

Ja, mag ich. Aber eben hatte ich kein Glück damit.

Komisch. Irre ich mich mit Harlequin? Oder haben die das aufgegeben?

von Michael (Gast)


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." ;-)

von Peter II (Gast)


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.

von Läubi .. (laeubi) Benutzerseite


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...

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Läubi .. schrieb:
> Mal mit einem passendem Tool (z.B. JProfiler) sich mal ansehen welche
> Objekte da immer mehr Speicher verbrauchen und den Bug fixen

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

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Peter II schrieb:
> ist nicht von uns die Anwendung, also kein Quelltext vorhanden

Bugreport? Jammern über Fehler die man nie meldet bringt ja wohl noch 
weniger...

von Andreas H. (ahz)


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

von (prx) A. K. (prx)


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.

von Hobbyist (Gast)


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 von außen niemand eines der Objekte referenziert, wird der ganze 
Zykel abgeräumt. Es muss immer eine Verbindung zur Wurzel bestehen.

von Peter II (Gast)


Lesenswert?

Hobbyist schrieb:
> Wenn von außen niemand eines der Objekte referenziert, wird der ganze
> Zykel abgeräumt. Es muss immer eine Verbindung zur Wurzel bestehen.

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

von Michael (Gast)


Lesenswert?

Doch, so einfach ist das. Denn ein "Threadobjekt" hat eine Verbindung 
zum Root-Set.

Hirntot sind GC-Entwickler nun nicht.

von Udo S. (urschmitt)


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!

von (prx) A. K. (prx)


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.

von Arc N. (arc)


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

von Jan H. (j_hansen)


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.

von Peter II (Gast)


Lesenswert?

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

von Arc N. (arc)


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...)

von (prx) A. K. (prx)


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.

von Claude M. (stoner)


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.

von Yalu X. (yalu) (Moderator)


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.

von Jan H. (j_hansen)


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.

von TB (Gast)


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.

von (prx) A. K. (prx)


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. ;-)

von Peter II (Gast)


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? )

von (prx) A. K. (prx)


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.

von (prx) A. K. (prx)


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

von Karl Käfer (Gast)


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

von Hobbyist (Gast)


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 
;-))

von (prx) A. K. (prx)


Lesenswert?

Jan Hansen schrieb:
> Als ob der Programmierer in C++ nicht noch ein viel größeres Memory-Leak
> produziert hätte.

Dem wäre statt dessen wahrscheinlich das Programm weggeflogen. Mit einem 
schönen sauberen Crash. Statt Tag für Tag langsamer zu werden, bis der 
Server aus Speichermangel die Grätsche macht.

von Mladen G. (mgira)


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.

von (prx) A. K. (prx)


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.

: Bearbeitet durch User
von Arc N. (arc)


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

von Karl Käfer (Gast)


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

von Yalu X. (yalu) (Moderator)


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 ;-)

von Dumdi D. (dumdidum)


Lesenswert?

Arc Net schrieb:
> benso ist eine manuelle Speicherverwaltung nicht perfekt. Stichworte
> u.a.: Heap fragmentation,

Haben GCs nicht auch dieses Problem?

von Udo S. (urschmitt)


Lesenswert?

Yalu X. schrieb:
> Und bei den heutzutage
> typischen 16GiB Hauptspeicher

Mann was hätten wir vor 25 Jahren mit so viel Ram angefangen? Wir hätten 
gar nicht gewusst was wir damit tun sollen :-)

von Arc N. (arc)


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.

von Jan H. (j_hansen)


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.

von Tobias K (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.