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?
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"
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.
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!
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.
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
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
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.
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)
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.
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?
Ist nicht wirklich mein Gebiet, aber ich weiß, daß Harlequin das hatte. Mittlerweile heißen die LispWorks.
Ich verzichte auf Controllern generell auf dynamischen Speicher. Waer bloed wenn's grad keinen mehr hat, oder nur zerstueckelt
:
Bearbeitet durch User
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
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
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.
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
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.
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
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.
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
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.
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.
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?
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." ;-)
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.
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
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.
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...
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
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.
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.
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.
Doch, so einfach ist das. Denn ein "Threadobjekt" hat eine Verbindung zum Root-Set. Hirntot sind GC-Entwickler nun nicht.
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!
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.
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
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.
Warum wird ein Filehandle nicht vom GC aufgeräumt wenn keine Referenz mehr da ist? Die Datei bleibt ewig geöffnet.
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...)
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.
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.
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.
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.
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.
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. ;-)
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? )
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.
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
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
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 ;-))
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.
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.
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
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
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
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 ;-)
Arc Net schrieb: > benso ist eine manuelle Speicherverwaltung nicht perfekt. Stichworte > u.a.: Heap fragmentation, Haben GCs nicht auch dieses Problem?
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 :-)
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.