[C++] Speicherfreigabe bei statischem Singleton

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Da magst du in den meisten Fällen Recht haben, ich persönlich habe aber z.B. absolut keinen Bock a) zentrale Log-Einrichtungen und b) zentrale Dateisystem-bezogene Daten überall per Parameter oder gar Members zu verteilen. ;-)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Ich hätte mich schon einmal entgegen all meiner Prinzipien fast dazu hinreißen lassen genau solche Dinge als Singleton anzulegen. Du glaubst gar nicht wie glücklich ich nach ein paar Monaten war dass ich das doch nicht getan hab ;)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Na dann, ich bin jedenfalls seit Jahren glücklich damit. :P Viel interessanter wäre aber, wie du es denn am Ende stattdessen gemacht hast. ;)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Na so wie mans Eben macht: Wenn ein Objekt ein andres benötigt bekommts ne Referenz drauf ;)
Das ist genau Problem mit Singleton: Es wird ständig als globaler Zugriffspunkt auf ein Objekt missbraucht. Genau das ist aber nicht der Sinn von Singleton, steht sogar explizit so im GoF Buch. Leider ist das der wohl am meisten missverstandene Satz der Softwareentwicklung...
Zuletzt geändert von dot am 01.06.2011, 15:30, insgesamt 2-mal geändert.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Iih, das kostet dann ja für jedes Objekt im ganzen Programm extra Speicher... ;) Ich weiß, dass das nicht der eigentliche Sinn von Singletons ist. Ich kann es ja ab sofort "globales Singleton" nennen, ein gänzlich neues und innovatives Entwurfsmuster, welches das klassische Singleton mit der klassischen globalen Variable verbindet. :mrgreen:

Nachtrag zum Post untendrunter: Bei mir loggen aber praktisch alle Objekte.

Nachträgliche Korrektur: Auch hier habe ich das Singleton-Muster mit der typischen statischen Klasseninstanz in der entsprechenden klassischen Singleton-Zugriffsmethode vermengt, welche ich eigentlich bereits zu diesem Zeitpunkt nicht länger als Singleton, sondern in einer entsprechenden freien Funktion und ohne Konstruktionsbeschränkung implementiert hatte. Eine ausführliche Diskussion mit Beispielen und Vergleich findet sich gegen Ende dieses Threads.
Zuletzt geändert von CodingCat am 12.09.2011, 12:08, insgesamt 3-mal geändert.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Bei den zwei, drei Objekten die eine Referenz auf das Log brauchen sowas von egal...
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

CodingCat hat geschrieben:Nachtrag zum Post untendrunter: Bei mir loggen aber praktisch alle Objekte.
Und das is sinnvoll?

CodingCat hat geschrieben:Ich kann es ja ab sofort "globales Singleton" nennen, ein gänzlich neues und innovatives Entwurfsmuster, welches das klassische Singleton mit der klassischen globalen Variable verbindet. :mrgreen:
Ich denk mehr muss man dazu nichtmehr sagen :P
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Was soll daran nicht sinnvoll sein? Ich hasse es, wenn Fehler auftreten, ohne dass ich was davon mitbekomme. Ich logge sogar jede Exception noch bevor sie fliegt. ;-) Aber oftmals will man eben keine Exception, und trotzdem was vom Fehler mitbekommen - was bei nicht behandelten Rückgabewerten sonst ja eher die Ausnahme wäre.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Für sowas verwend ich einen Debugger. Ein Log verwend ich für grobe Diagnose wenn beim Kunden was schiefläuft wo ich nicht direkt Debuggen kann. Da kommen so Sachen rein wie irgendwelche Fehler beim Laden oder was für eine Hardwarekonfiguration der Rechner hat und welche Versionen einzelner Komponenten verwendet werden und das hat mir schon viel Schmerz erspart. Aber alles und überall zu loggen hat sich für mich noch nie als sinnvoll herausgestellt...
CodingCat hat geschrieben:Aber oftmals will man eben keine Exception, und trotzdem was vom Fehler mitbekommen.
assert() ;)
Zuletzt geändert von dot am 01.06.2011, 15:42, insgesamt 1-mal geändert.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Naja, das kommt halt sehr auf das Projekt und seine Größe an - mit dem Debugger kriege ich eben doch mehr das mit, was ich mir gerade gezielt ansehe, und lang nicht alles, was gerade schief laufen könnte. Und das Logging kostet mich praktisch nichts, warum also nicht das Maximum an Information mitnehmen. Ja, assert nutze ich auch. Aber nicht für Fehler, die sich prinzipiell ignorieren lassen.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

CodingCat hat geschrieben:Und das Logging kostet mich praktisch nichts, warum also nicht das Maximum an Information mitnehmen.
Weil die wirklich wichtige Information dann im Rest untergeht.
CodingCat hat geschrieben:Ja, assert nutze ich auch. Aber nicht für Fehler, die sich prinzipiell ignorieren lassen.
Gut, die Art von Fehler hatte ich wohl noch nie ;)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Wow, heute komme ich noch zu meinem absoluten Post-Rekord. :P
Weil die wirklich wichtige Information dann im Rest untergeht.
Ich glaube du verstehst mich falsch, ich logge nicht alles was passiert, sondern alles was schief geht, das ist in der Regel nichts. ;-)
Gut, die Art von Fehler hatte ich wohl noch nie.
Du Glücklicher. :)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8375
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Ein Log ist doch nicht nur für den einen tödlichen Fehler da, der das Programm abschießt, sondern um nachvollziehen zu können, wie es dazu kam. Das Problem am Debugger ist, dass man nur den aktuellen Zustand sieht und alles zuvor geschehene verloren ist. Wenn im Programm erstmal vollkommen andere Daten sind als man für den Lauf erwartet hätte (was ja nicht heißt, dass sie beim Laden ungültig waren oder man den Fehler anderweitig früher hätte erkennen können!) und man nicht geloggt hat, dass das System seine ganzen Caches erneuert hat und komplett andere Daten durchgegangen ist als es sollte weil man einen falschen Login eingetippt hat, kann man die gesamte Ausführung im Debugger durchsteppen. Je größer die Fehlertoleranz eines Systems (die eine Anforderung sein kann!), desto schlimmer wird es.

Auf ein Log kann ich, und imo jeder, genauso wenig verzichten wie auf Ausnahmen oder assert. Es gibt halt nicht den Fehler an sich, von dem ihr hier redet. In Flugzeugen verzichtet man auch nicht mit dem Verweis auf die hohe Zuverlässigkeit und Testabdeckung auf die Black Box (oder nimmt damit nur den Start auf „damit keine wirklich wichtige Information im Rest untergeht“).
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Schon klar, aber ich hatte noch nie soviele Objekte die etwas loggen müssen dass eine globale Variable für das Log notwendig geworden wäre um den Speicherverbrauch durch die Dependency Injection zu sparen oO
Es ist jedenfalls sicherlich nicht so dass jedes einzelne kleine Sprite was loggen muss. Wenn dann vielleicht die Klasse die die Sprites erzeugt...
Zuletzt geändert von dot am 01.06.2011, 16:33, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8375
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Ich ganz persönlich hatte auch noch nie so viele unterschiedliche Logs, dass ich mehr als eine globale Variable bzw. Funktion gebraucht hätte. (Jetzt dürft ihr mich stiefeln)
Halt jedem das Seine, oder jeder das Ihrige, oder allen das Essig.
dot hat geschrieben:Es ist jedenfalls sicherlich nicht so dass jedes einzelne kleine Sprite was loggen muss. Wenn dann vielleicht die Klasse die die Sprites erzeugt...
Imo muss man Fehler loggen, sobald sie auftreten. Das bedeutet, dass jede Ausnahme beim Werfen eine Referenz auf den Logger braucht. Kann also bei der Sprite was schiefgehen, braucht sie ihn meiner Einschätzung nach durchaus.
Zuletzt geändert von Krishty am 01.06.2011, 16:34, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Krishty hat geschrieben:Ich ganz persönlich hatte auch noch nie so viele unterschiedliche Logs, dass ich mehr als eine globale Variable bzw. Funktion gebraucht hätte.
Gut, dann ist aber eine globale Variable ausreichend, ein Singleton wäre imo falsch. Der einzige wirkliche Anwendungsfall der mir bisher je untergekommen ist wo ein Singleton evtl. sinnvoll sein könnte ist ein Scheduler in einem Betriebssystem. Bei dem ist es evtl. wirklich eine wesentliche Eigenschaft des Typs dass nur genau eine Instanz existieren darf. Aber selbst da wär ich persönlich sehr skeptisch und würd vermutlich eher kein Singleton verwenden.
Zuletzt geändert von dot am 01.06.2011, 16:41, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8375
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

dot hat geschrieben:Gut, dann ist aber eine globale Variable ausreichend, ein Singleton wäre imo einfach nur falsch.
Die Sache hat aber auch ein Haken: Und das ist C++’ völlig bescheuerte undefinierte statische Initialisierungsreihenfolge. Du kannst darum keine anderen globalen Variablen mehr bei ihrer Initialisierung was loggen lassen – in eine Funktion verpackt hingegen hat man einen eindeutigen Initialisierungszeitpunkt (den Augenblick, in dem es zuerst gebraucht wird).

Ob man dann ein Singleton hat oder nicht hängt dann nurnoch davon ab, ob diese Funktion innerhalb oder außerhalb der Klasse liegt. Für mich eine Formfrage. Darum ist das Singleton auch meines Ermessens nach nicht pauschal falsch.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Krishty hat geschrieben:Die Sache hat aber auch ein Haken: Und das ist C++’ völlig bescheuerte undefinierte statische Initialisierungsreihenfolge. Du kannst darum keine anderen globalen Variablen mehr bei ihrer Initialisierung was loggen lassen – in eine Funktion verpackt hingegen hat man einen eindeutigen Initialisierungszeitpunkt (den Augenblick, in dem es zuerst gebraucht wird).
Ok, das ist zugegeben ein Argument. Allerdings hat man dieses Problem mit Dependency Injection schon rein prinzipell nicht da der Fall dort systematisch bedingt nie eintreten kann. Und daher würde ich letzeres als die definitiv bessere Lösung ansehen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8375
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

dot hat geschrieben:Allerdings hat man dieses Problem mit Dependency Injection schon rein prinzipell nicht da der Fall dort systematisch bedingt nie eintreten kann.
Wo wir gerade bei Objektorientierungsgrundsätzen sind: Ich für meinen Teil überlege schon lange, ob ich Logging überhaupt objektorientiert handhaben soll und nicht etwa funktional – ich empfinde den Logger mehr und mehr als Gespenst von etwas völlig Funktionalem, was ich nur extrem verkompliziere. Wenn tatsächlich irgendwer loggt, ist das imo eine Handlung meines kompletten Prozesses, also … riecht das nach globaler Funktion.

Zurückgehalten werde ich nur von der Leistung und der Überschaubarkeit der Syntax (log << blubb << "foo"; ist halt eleganter und schneller als log(toString("blubb") + "foo")).

Einfach mal neben die Tüte gekotzt.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Ja, bzgl. globalem Zugriff habe ich Krishty nichts mehr hinzuzufügen. Um nochmal auf das Singleton zurückzukommen, hier hatten wir uns ja schon auf Seite 2 geeinigt, dass ich Singleton im Eingangspost zum Thema Logging zu sehr mit globalem Zugriff vermengt hatte. Die Ursache hierfür, das C++-Singleton-typische Muster der lokal definierten statischen Variable, hat Krishty eben auch schon genannt. Tatsächlich nutze ich zum Logging sogar eine statische Instanz, die lokal in einer freien Funktion definiert ist, ohne dass die Anzahl der konstruierbaren Instanzen prinzipiell beschränkt ist.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Ja, das ist eine gute Frage. Logging ist so eine Sache wo ich auch noch keine wirklich zufriedenstellende Lösung gefunden hab. Ein Log ist sicherlich einer der extrem seltenen Fälle wo man wirklich für ein Singleton oder eine globale Variable argumentieren kann (das wohl beste Argument hast du ja oben gebracht) und ich will ja nicht Cat's Lösung runtermachen oder so. Ich find nur Singleton rein prinzipiell so hässlich dass ich in dem Kontext gern immer ein wenig übertreib, ich persönlich würds, was auch immer passiert, einfach nie tun ;)
Für sehr einfache Dinge verwend ich evtl. einfach einen globalen std::ofstream log("log.txt") und fertig. Streams sind halt sehr angenehm. Logging ist auch eine der wenigen Sachen wo ich mich evtl. für den Einsatz von Makros erwärmen kann da automatisches Mitloggen von File und Zeile eben doch angenehm ist. Man kann sich natürlich alles Mögliche einfallen lassen, wie wärs z.B. mit sowas:

Code: Alles auswählen

log(ERROR() << "foo " << 42);
Ein Makro log() dass eine entsprechende Funktion mit __FILE__ und __LINE__ aufruft die vielleicht für die verschiedenen Typen ERROR() und WARNING() überladen ist die selbst eben jeweils Streamoperationen unterstützen.
Oder einfach:

Code: Alles auswählen

log << ERROR("foo " << 42);
Das ließe sich direkt in eine Ausgabe auf einen Stream übersetzen. Prinzipiell fallen mir da alle 5 min. neue Möglichkeiten ein^^
Zuletzt geändert von dot am 01.06.2011, 17:17, insgesamt 1-mal geändert.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4307
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

MMh habt ihr schon mal gesehen was man mit Log4J bzw. java.util.logging und so machen kann? Die Komplexität von Logging sollte man nicht unterschätzen. Man sollte z.B. in der lage sein, pro Modul bzw. Klasse in unterschiedliche Logs zu schreiben ohne das im Code angeben zu müssen. Z.B. kann es im Produktiv-Betrieb sinnvoll sein, Meldungen eines bestimmten Moduls bestimmter Warnstufe per Email zu versenden etc. Das Ausgabeformat sollte auch konfigurierbar sein XML, HTML, TXT usw. Es gibt sowas wie log4j bestimmt auch für C++.
Zuletzt geändert von Chromanoid am 01.06.2011, 17:20, insgesamt 1-mal geändert.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

Ja, hier sind Makros ausnahmsweise wirklich Gold wert, __LINE__ und __FILE__ machen das Leben einfach enorm leichter. Der globale std::ofstream ist halt wieder extrem problematisch in Bezug auf Initialisierungsreihenfolge. Deshalb ist das für mich keine Alternative zur lokal definierten statischen Variable, Singleton muss ja deshalb nicht (und sollte womöglich auch, wie eben angemerkt, nicht) sein.

Den Vorteil gegenüber (mehreren) globalen Funktionen sehe ich darin, dass der immer notwendige zentrale Zugriffspunkt auf das Bezugsobjekt automatisch dafür sorgt, dass dieses Objekt dort auch tatsächlich erzeugt wird. Bei mehreren Overloads einer globalen Funktion müsste derartiges Verhalten schon wieder in alle Funktionen kopiert werden.

Nachtrag: Krishty merkte gerade an, dass am Ende immer Buchstaben ausgegeben werden müssen, und die entsprechende zugrundeliegende Funktion dann problemlos die Initialisierung übernehmen kann.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Brainsmith
Establishment
Beiträge: 109
Registriert: 04.09.2009, 13:52
Echter Name: Fabbo

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Brainsmith »

Huch, hab mich ganz schön erschreckt, als ich hier reingeschaut hab.. So viele neue Posts.

Also.. Das Makro benutze ich auch nicht. Ich habe das nur geschrieben, um klarzumachen, wie der Singleton definiert ist. Und nun mal eine andere Frage:

Ich habe das Gefühl, dass hier mehrere Leute Singletons nicht mögen. Warum ist das so?
In meinem Falle geht es um eine Sound Engine. Ich will halt nicht, dass jemand versucht, das Ding zweimal zu initialisieren.

Wo wir aber gerade dabei sind. Gibt es Performance-Nachteile bei nem statischen Singleton? Das wäre für mich das einzige Argument, was zählt.
Benutzeravatar
Schrompf
Moderator
Beiträge: 5237
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Schrompf »

Brainsmith hat geschrieben: Ich habe das Gefühl, dass hier mehrere Leute Singletons nicht mögen. Warum ist das so?
In meinem Falle geht es um eine Sound Engine. Ich will halt nicht, dass jemand versucht, das Ding zweimal zu initialisieren.
Und wem bitte soll das "aus Versehen" passieren? Mal ganz davon abgesehen, dass auf allen aktuellen Betriebssystemen zwei parallele Sound Engines stressfrei möglich sind.

Zum Thema "nicht mögen": ich kann nicht für die anderen sprechen, aber ich persönlich habe schon mehrmals Singletons wieder entfernen müssen, weil der "Zu aller Zeit nur diese eine Instanz" einem halt immer irgendwann auf die Füße fallen wird. Und aus heutiger Sicht kann ich nur noch den Kopf schütteln, wenn Leute extra Arbeit und Code auf eine Aufgabe verschwenden, um einen ernsthaften Designfehler in ihrer Softwarearchitektur festzunageln. Wenn es momentan schön bequem ist, eine globale Instanz zu haben, na dann sollen sie halt eine anlegen.

Singletons würde ich nur in dem Fall benutzen, wo der Konstruktor nach Bedarf beim ersten Aufruf laufen soll, ohne dass ich mit normalem Code vorher was einrichten kann.
Wo wir aber gerade dabei sind. Gibt es Performance-Nachteile bei nem statischen Singleton? Das wäre für mich das einzige Argument, was zählt.
Ja, es kostet bei jedem get() die Rechenzeit, auf Existenz der Instanz zu prüfen, um sie notfalls anlegen zu können. Bei einer "static" Instanz erzeugt der Compiler diesen Code für Dich, aber die Rechenzeit ist dieselbe. Wenig, aber nicht Null.
Zuletzt geändert von Schrompf am 02.06.2011, 12:48, insgesamt 1-mal geändert.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8375
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Brainsmith hat geschrieben:Gibt es Performance-Nachteile bei nem statischen Singleton? Das wäre für mich das einzige Argument, was zählt.
Dann triffst du höchstwahrscheinlich alle deine Entwurfsentscheidungen auf völlig verkehrter Grundlage.

Was das Singleton an sich angeht: Wenn du eine globale Abhängigkeit hast, ändert sich daran auch nichts, wenn du sie in einer Funktion verpackst. Du machst dir nur ein bisschen mehr Arbeit, aber die ist Verschwendung weil die Abhängigkeit an sich bleibt. Was jedoch wiederum dafür spricht ist, wie erwähnt, die undefinierte Initialisierungsreihenfolge bei globalen Instanzen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Brainsmith
Establishment
Beiträge: 109
Registriert: 04.09.2009, 13:52
Echter Name: Fabbo

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Brainsmith »

Schrompf hat geschrieben:
Brainsmith hat geschrieben: Ich habe das Gefühl, dass hier mehrere Leute Singletons nicht mögen. Warum ist das so?
In meinem Falle geht es um eine Sound Engine. Ich will halt nicht, dass jemand versucht, das Ding zweimal zu initialisieren.
Und wem bitte soll das "aus Versehen" passieren? Mal ganz davon abgesehen, dass auf allen aktuellen Betriebssystemen zwei parallele Sound Engines stressfrei möglich sind.
Man muss immer vom dümmsten User ausgehen, den man sich denken kann. =D

Wo wir aber gerade dabei sind. Gibt es Performance-Nachteile bei nem statischen Singleton? Das wäre für mich das einzige Argument, was zählt.
Ja, es kostet bei jedem get() die Rechenzeit, auf Existenz der Instanz zu prüfen, um sie notfalls anlegen zu können. Bei einer "static" Instanz erzeugt der Compiler diesen Code für Dich, aber die Rechenzeit ist dieselbe. Wenig, aber nicht Null.
Hmm.. da habeich wohl etwas falsch verstanden. Ich dachte, wenn der Singleton statisch ist, wird der direkt zu Beginn auf den Stack gelegt und dann einfach nur imemr wieder geholt, falls notwendig.
In dem Fall ist es aber immernoch Meckern auf hohem Niveau. Wie oft greift man schon per GetInstance darauf zu? Im Regelfall passiert das dann auch nicht zur Laufzeit, sondern zur Ladezeit. Da kann ich die paar Abfragen noch verkraften.
Krishty hat geschrieben:
Brainsmith hat geschrieben:Gibt es Performance-Nachteile bei nem statischen Singleton? Das wäre für mich das einzige Argument, was zählt.
Dann triffst du höchstwahrscheinlich alle deine Entwurfsentscheidungen auf völlig verkehrter Grundlage.
Okay, ich bin ja lernbereit. Bitte kläre mich auf. Ich sehe den Punkt einfach nicht. Das, was zählt, ist Performance. Dabei ist es mir bisher völlig egal gewesen, ob etwas mal nicht objektorientiert war oder ob der Code für andere nicht leserlich ist. Dafür gibts ja auch Kommentare. Und schlechter wartbar ist der Code dadurch auch nicht. Also wäre es nett, wenn du da ein wenig ins Details gehen könntest.

Ps: Der letzte Teil hört sich evtl ein wenig zickig an. Ist nicht so gemeint. Ich meine das schon ernst, was ich da schreibe. =D
Benutzeravatar
Krishty
Establishment
Beiträge: 8375
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Brainsmith hat geschrieben:Okay, ich bin ja lernbereit. Bitte kläre mich auf. Ich sehe den Punkt einfach nicht. Das, was zählt, ist Performance. Dabei ist es mir bisher völlig egal gewesen, ob etwas mal nicht objektorientiert war oder ob der Code für andere nicht leserlich ist. Dafür gibts ja auch Kommentare. Und schlechter wartbar ist der Code dadurch auch nicht. Also wäre es nett, wenn du da ein wenig ins Details gehen könntest.

Ps: Der letzte Teil hört sich evtl ein wenig zickig an. Ist nicht so gemeint. Ich meine das schon ernst, was ich da schreibe. =D
Es gibt generell nur einen Punkt, wo Leistung ein Entscheidungskriterium ist: Nämlich, wenn du einen Algorithmus für die Lösung deines Problems aussuchst; und dann ist die Leistung in Laufzeitverhalten zu bewerten. Ansonsten geht es fast immer darum, das Problem so einfach wie möglich (so wenig komplex wie möglich, mit so wenig Quelltext wie möglich, mit so wenig Aufwand wie möglich) zu lösen. Einen Algorithmus zu wählen, der dein Problem in O(n×log(n)) löst statt in O(n²) wird dir mehr Leistung bringen als alle anderen Optimierungen, die du unter Einbußen von Wartbarkeit, Lesbarkeit und – vor allem – Zeit jemals zusammenschaben kannst, zusammen.

Und wenn es dann doch noch zu langsam ist, dann nicht wegen irgendeinem Singleton sondern wegen dem einen Prozent deines Quelltexts, der die innerste Schleife ausmacht. Den kannst du dann oft immernoch optimieren ohne den Rest kaputtzumachen. Oft ist es dann aber auch so, dass die simpelste Lösung am schnellsten abgearbeitet wird.

Ist natürlich nur eine Faustregel. Wenn man im Embedded-Bereich Pixel zusammenschabt oder auf der GPU hunderte Recheneinheiten füttern muss, verhält sich das u.U. kontraintuitiv (weil das übliche Bild vom Laufzeitverhalten durch Speicherlatenzen, Branching oder Flaschenhälse bei bestimmten Vorgängen verzerrt wird – oder weil die Compiler einen feuchten Kehricht wert sind). Wenn du aber bei einem normalen PC-Spiel alle deine Entscheidungen zeilenmäßig nach Leistung fällst, steuerst du langfristig auf eine Katastrophe zu.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Brainsmith
Establishment
Beiträge: 109
Registriert: 04.09.2009, 13:52
Echter Name: Fabbo

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Brainsmith »

Krishty hat geschrieben:
Brainsmith hat geschrieben:Okay, ich bin ja lernbereit. Bitte kläre mich auf. Ich sehe den Punkt einfach nicht. Das, was zählt, ist Performance. Dabei ist es mir bisher völlig egal gewesen, ob etwas mal nicht objektorientiert war oder ob der Code für andere nicht leserlich ist. Dafür gibts ja auch Kommentare. Und schlechter wartbar ist der Code dadurch auch nicht. Also wäre es nett, wenn du da ein wenig ins Details gehen könntest.

Ps: Der letzte Teil hört sich evtl ein wenig zickig an. Ist nicht so gemeint. Ich meine das schon ernst, was ich da schreibe. =D
Es gibt generell nur einen Punkt, wo Leistung ein Entscheidungskriterium ist: Nämlich, wenn du einen Algorithmus für die Lösung deines Problems aussuchst; und dann ist die Leistung in Laufzeitverhalten zu bewerten. Ansonsten geht es fast immer darum, das Problem so einfach wie möglich (so wenig komplex wie möglich, mit so wenig Quelltext wie möglich, mit so wenig Aufwand wie möglich) zu lösen. Einen Algorithmus zu wählen, der dein Problem in O(n×log(n)) löst statt in O(n²) wird dir mehr Leistung bringen als alle anderen Optimierungen, die du unter Einbußen von Wartbarkeit, Lesbarkeit und – vor allem – Zeit jemals zusammenschaben kannst, zusammen.

Und wenn es dann doch noch zu langsam ist, dann nicht wegen irgendeinem Singleton sondern wegen dem einen Prozent deines Quelltexts, der die innerste Schleife ausmacht. Den kannst du dann oft immernoch optimieren ohne den Rest kaputtzumachen. Oft ist es dann aber auch so, dass die simpelste Lösung am schnellsten abgearbeitet wird.

Ist natürlich nur eine Faustregel. Wenn man im Embedded-Bereich Pixel zusammenschabt oder auf der GPU hunderte Recheneinheiten füttern muss, verhält sich das u.U. kontraintuitiv (weil das übliche Bild vom Laufzeitverhalten durch Speicherlatenzen, Branching oder Flaschenhälse bei bestimmten Vorgängen verzerrt wird – oder weil die Compiler einen feuchten Kehricht wert sind). Wenn du aber bei einem normalen PC-Spiel alle deine Entscheidungen nach Leistung fällst, steuerst du langfristig auf eine Katastrophe zu.

Ich hab mich vielleicht etwas drastisch ausgedrückt. Natürlich ist Wartbarkeit ein Kriterium, wie auch die Geschwindigkeit, in der der Code geschrieben wird. Bei einem Singleton hält sich das natürlich auch in Grenzen.
Ich glaube aber, ich habe den Punkt gefunden, wo unsere Meinungen differieren:
Es gibt generell nur einen Punkt, wo Leistung ein Entscheidungskriterium ist: Nämlich, wenn du einen Algorithmus für die Lösung deines Problems aussuchst
Die Sache ist dann doch eher, was man als Problem definiert. Ich sehe es meist so, dass alles, was ich programmiere in gewisser Weise ein Problem ist, weshalb diese Regel auch fast immer greift. Andererseits ist mir natürlich auch bewusst, was du meinst (Optimieren am falschen Ende vermeiden). Eine Frage ist aber auch: Was ist angenehmer: Im Nachhinein nochmal über den Code zu schauen und Optimierungen vorzunehmen oder den Code direkt so zu schreiben, dass solche Schritte unnötig sind. Dadurch ergibt sich mir dann die Folgefrage, welche Methode letztendlich schneller ist, wenn man die jeweilge Methde gwöhnt ist.
Scheinbar wird es als Axiom angesehen, dass der eine Workflow besser ist, als der andere. Falls jemand einen repräsentativen Artikel zum Thema hat, wäre ich sehr dankbar. Nur weil ein Ansatz für viele gilt, bedeutet dies nicht automatisch, dass er für alle richtig ist.

Zusätzlich dazu fühle ich mich immer furchtbar, wenn ich Code geschrieben habe, von dem ich weiß, dass er schneller sein könnte. Da möchte ich am liebsten wild mit einem Auge zucken und alles neu schreiben. :D
Wenn du aber bei einem normalen PC-Spiel alle deine Entscheidungen zeilenmäßig nach Leistung fällst, steuerst du langfristig auf eine Katastrophe zu.
Naja, ich treffe die Entscheidungen natürlich nicht zeilenmäßig, sondern problemmäßig nach Leistung (natürlich nur nach meinem doch recht.. sagen wir mal beschränkten Wissen).
Und tatsächlich gibt es auch Plattformen, wo man absolut effizient programmieren muss, wie zum Beispiel den Nintendo DS, wenn man da was rausholen will.
Ich habe mit dieser Einstellung in zwei kommerziellen Projekten gearbeitet und keine Probleme damit gehabt. Weder zeitlich, noch hat jemand die Lesbarkeit meines Codes bemängelt.

ich schließe natürlich die Möglichkeit nicht aus, dass wir gnadenlos aneinander vorbei schreiben und wir zB Sachen wie Lesbarkeit, Wartbarkeit etc. unterschiedlich definieren. Zumindest der Lesbarkeitsbegriff ist doch eher schwammig.
Benutzeravatar
dot
Establishment
Beiträge: 1748
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Auf der einen Seite argumentierst du dass für dich nur rohe Performance zählt, auf der anderen Seite hast du bei einer typischen Implementierung des Singleton Pattern (z.B. Meyers Singleton) wie Schrompf schon sagte bei jedem Zugriff auf den Singleton infolge der statischen Variable mit gewissem Overhead zu rechnen (der Compiler muss ja Code einbaun der checked ob die Variable schon initialisiert wurde). Und dabei ist das Ding noch nichtmal annähernd Thread-Safe.

Wie schon gesagt: Das Hauptproblem von Singleton ist dass es praktisch immer für eine globale Instanz missbraucht wird. Manche nennen es sogar eine "objektorientierte Lösung für eine globale Variable" und solche Dinge, als ob es durch eine nette Verpackung besser würde. Genau dafür war Singleton per Definition nie gedacht. Ich hab sicher schon hunderte Singletons gesehn und jedes einzelne davon war ein grober Designfehler, was tut man nicht alles für etwas vermeintliche Bequemlichkeit? Singleton verschleiert Abhängigkeiten. Aber nur weil du sie nicht siehst heißt das noch lange nicht dass sie nicht da sind. Sogar rein theoretische Beispiele für den korrekten Einsatz von Singleton sind extrem rar und selbst dort findet man praktisch immer genug Gegenargumente und bessere Alternativen.

Singletons sind wie Krebs: Wenn du merkst dass du sie hast ist es meistens schon zu spät, denn das Singleton hat bereits überall in deinen Code metastasiert.
Antworten