Schlanke Smartpointer-Implementierung?
-
Den Deleter.
-
Damit spart man sich die Grösse eines Funktionszeigers im Speicher und einen Funktionsaufruf über diesen Funktionszeiger der dann evtl. komplett wegoptmiert werden kann.
Dort wo shared_ptr zum Einsatz kommen wird beides kein echter Anreiz.
(Den wirklich "bösen" Overhead, nämlich die zusätzliche Allokation für das Counter-Objekt, bekommt man damit aber nicht weg. Das geht nur mit Tricks wie make_shared, und die funktionieren genau so mit Deleter und Weak-Count und allem.)
-
Deleter kannst du meines Wissens komplett in die Tonne kloppen.
-
. o O ( Großes Kino hier ... wartet kurz, ich geh' mir ein Joghurt pflücken
)
-
When I lookup bloat in the lexicon I see "boost".
-
So, ich habe es einfach mal ausprobiert und in einer bestehenden Applikation ein paar Pointer durch boost::shared_ptr ersetzt. Der resultierende Code (Release-Build, Symbol-stripped) war um gut 20 KBytes größer - was für das bisschen Funktionalität schon mehr als knackig ist. So 1..2 KBytes hätte ich erwartet und die wären auch OK gewesen, aber dieses Ergebnis ist schon sehr überraschend.
-
Ein shared_ptr ist auch nicht bloß "ein bisschen" Funktionalität mehr als ein normaler nackter Pointer. Wenn du glaubst, dass die Größe der Implementierung irgendeine Rolle spielt, dann vergleich einen selbstgeschriebenen shared_pointer oder einen aus einer anderen Bibliothek mit dem von Boost. Du wirst dann keine nennenswerten Unterschiede mehr messen können.
-
RayOfLight schrieb:
So, ich habe es einfach mal ausprobiert und in einer bestehenden Applikation ein paar Pointer durch boost::shared_ptr ersetzt. Der resultierende Code (Release-Build, Symbol-stripped) war um gut 20 KBytes größer - was für das bisschen Funktionalität schon mehr als knackig ist. So 1..2 KBytes hätte ich erwartet und die wären auch OK gewesen, aber dieses Ergebnis ist schon sehr überraschend.
Das ist nun mal der Preis für ein bisschen mehr Komfort, genau wie im richtigem Leben.

-
Burkhi schrieb:
Das ist nun mal der Preis für ein bisschen mehr Komfort, genau wie im richtigem Leben.

Nur genau wie im richtigen Leben sollte auch die Verhältnismäßigkeit gegeben sein: in 4 KBytes bringt man ganze Grafikdemos samt Bildern, Sound und 3D Animationen unter, Boost benötigt 20 KBytes um ein paar Zähler zu bedienen und Speicher freizugeben (und ich rede wirklich von 20 KBytes effektivem Binärcode, der gesamte Executable/Linker-Overhead ist da schon gar nicht mitgezählt).
-
RayOfLight schrieb:
Burkhi schrieb:
Das ist nun mal der Preis für ein bisschen mehr Komfort, genau wie im richtigem Leben.

Nur genau wie im richtigen Leben sollte auch die Verhältnismäßigkeit gegeben sein: in 4 KBytes bringt man ganze Grafikdemos samt Bildern, Sound und 3D Animationen unter, Boost benötigt 20 KBytes um ein paar Zähler zu bedienen und Speicher freizugeben (und ich rede wirklich von 20 KBytes effektivem Binärcode, der gesamte Executable/Linker-Overhead ist da schon gar nicht mitgezählt).
Absolut irrelevant. Der Code wird nicht auf diese Weise optimiert, weil 20K egal sind. Viel wichtiger ist es dass der Code schnell abläuft.
Und das bedeutet, dass der Code länger wird. Man kann ihn natürlich auch kleiner bekommen, nur hat man dann langsameren Code. Und das wollen die meisten Leute nicht, deshalb nimmt man halt die sinnvollste Optimierung.
Und shared_ptr ist ja auch nicht nur einfach ein Zeiger - das ist eine enorm komplexe Angelegenheit - ein bisschen mit einem GC vergleichbar.
-
Shade Of Mine schrieb:
Der Code wird nicht auf diese Weise optimiert, weil 20K egal sind. Viel wichtiger ist es dass der Code schnell abläuft.
Und das bedeutet, dass der Code länger wird. Man kann ihn natürlich auch kleiner bekommen, nur hat man dann langsameren Code.
Ähm...vielleicht solltest du dir meinen Link oben erst mal ansehen bevor du sowas öffentlich behauptest...
-
RayOfLight schrieb:
Shade Of Mine schrieb:
Der Code wird nicht auf diese Weise optimiert, weil 20K egal sind. Viel wichtiger ist es dass der Code schnell abläuft.
Und das bedeutet, dass der Code länger wird. Man kann ihn natürlich auch kleiner bekommen, nur hat man dann langsameren Code.
Ähm...vielleicht solltest du dir meinen Link oben erst mal ansehen bevor du sowas öffentlich behauptest...
Braucht er nicht, weil er recht hat. Das ist auf Größe optimierter Code, der sich zur Laufzeit auf gigantische Größen im Speicher auspackt, und zur Ausführung leistungsstarke Maschinen benötigt.
-
Shade Of Mine schrieb:
das ist eine enorm komplexe Angelegenheit
Eine sehr subjektive Behauptung. Ich finde shared_ptr ziemlich primitiv.
Shade Of Mine schrieb:
ein bisschen mit einem GC vergleichbar.
Ne, ein GC arbeitet komplett anders.
-
RayOfLight schrieb:
Ähm...vielleicht solltest du dir meinen Link oben erst mal ansehen bevor du sowas öffentlich behauptest...
In solchen Umfeldern wird man aber auch keine Smartpointer mit Referenzzählung verwenden, eben wegen ihren Overhead. Für die meisten Anwendungsfälle ist dieser Overhead wiederum absolut zu vernachlässigen.
Wenn man wirklich eine sehr kleine exe haben will, programmiert man in der Regel wesentlich mehr zu Fuß und optimiert wesentlich stärker. Für andere Anwendungen wiederum spielt die Entwicklungszeit (und damit der Komfort) eine wesentlich größere Rolle als beispielsweise 20kb.
-
Pis Halbwissen nervt (mal wieder).
-
Weil ich hier ja auch so viele Aussagen hingeschrieben habe, in denen Halbwissen überhaupt vorkommen könnte...

-
314159265358979 schrieb:
Eine sehr subjektive Behauptung. Ich finde shared_ptr ziemlich primitiv.
Hast du dir wirklich mal alle Fähigkeiten des shared_ptr angesehen (ich meine auch solche wie das zusammenspiel mit weak_ptr, enable_shared_from_this...)?
Man kann auch einfachere Implementierungen machen, wenn man auf das ein oder andere verzichten kann (z.B. auf den weak_ptr), ich hatte vor längeren in einer Firma händisch einen solchen in Anlehnung auf eine Implementierung von Scott Meyers geschrieben. Die war zwar schlanker, konnte aber auch wesentlich weniger (Mit einer Realisierung die stark an eine doppelt verkettete Liste erinnert hat, ohne einer Referenzzählung).
314159265358979 schrieb:
Shade Of Mine schrieb:
ein bisschen mit einem GC vergleichbar.
Ne, ein GC arbeitet komplett anders.
Die Grundidee geht aber in eine ähnliche Richtung, und der shared_ptr kommt den grundlegenden Denkansätzen eines GC doch schon nahe.
-
asc schrieb:
Hast du dir wirklich mal alle Fähigkeiten des shared_ptr angesehen (ich meine auch solche wie das zusammenspiel mit weak_ptr, enable_shared_from_this...)?
Ja.
asc schrieb:
Man kann auch einfachere Implementierungen machen, wenn man auf das ein oder andere verzichten kann (z.B. auf den weak_ptr), ich hatte vor längeren in einer Firma händisch einen solchen in Anlehnung auf eine Implementierung von Scott Meyers geschrieben. Die war zwar schlanker, konnte aber auch wesentlich weniger (Mit einer Realisierung die stark an eine doppelt verkettete Liste erinnert hat, ohne einer Referenzzählung).
Also reference linked Smartpointer.
-
In jedem seinem Posting merkt man, wie Pi nach Anerkennung bettelt.

-
Wenn man möglichst effizient und schlank bleiben wollen will, würde ich einfach eine Basis für reference-counted objects schreiben:
class reference_counted { private: std::atomic_uint m_ref; public: void inc_ref() { ++m_ref; } void dec_ref() { if(std::atomic_fetch_sub(&m_ref, 1) == 0) delete this; } };Und davon halt alle Klassen ableiten + einen smart pointer schreiben der nur inc_ref/dec_ref aufruft. Fertig.