Speicherverbrauch shared_ptr und normaler *


  • Mod

    booster schrieb:

    1. Ja

    Dann ist set die Datenstruktur, die du suchst, nicht map. => doppelte Strings vermieden

    booster schrieb:

    2. Die TreeCollection ist genau so aufgebaut wie die Variablenstruktur in der SPS. Also es gibt etwa 1000 Variablen auf oberster ebene. Alle anderen sind dann wiederum Kinder und Enkelkinder usw. also SubSymbols genannt.
    In der FlatCollection liegen alle Variablen bis in tiefster Ebene auf selber Ebene.

    Was heisst selbe Ebene? Es ist relativ einfach, einen Iterator zu schreiben, der den gesamten Baum durchlaufen kann. => Speicherverbrauch halbiert.

    booster schrieb:

    3. Also jedes Symbol ist genau einmal vorhanden.

    Der Name (im Gegensatz zum short Name) ist aber zusammengesetzt.
    Also z.B.
    Oberste Varible heißt "MyFunctionBlock"
    Dann heißt die Variable darunter "MyFunctionBlock.MyStruct"
    und die wieder darunter
    "MyFunctionBlock.MyStruct.MyArray"

    name ist einfach zusammengesetzt aus shortName der parents plus short Name des Elements, getrennt duch Punkte? Dann ist das völlig überflüssige Speicherverschendung. Unter diesen Bedingungen ist dein FindSymbol auch doppelt ineffizient (einerseits O(N) statt O(log N) beim Durchlaufen des Baumes, und andererseits sind die zu vergleichenden Strings unnötig lang).

    Ich sehe auch keinerlei Notwendigkeit hier überhaupt irgendeine Form von Zeigern einzusetzen. Das ganze könnte also ungefär so aussehen

    class AdsSymbol
    {
        ITcAdsSymbol symbol;
    
        AdsSymbol(const AdsSymbol&) = delete;
        AdsSymbol& operator=(const AdsSymbol&) = delete;
        AdsSymbol(AdsSymbol&&); // ggf. Zeiger in _subSymbols auf parent anpassen
        AdsSymbol& operator=(AdsSymbol&&);
    
        struct SymbolCompare {
            template <typename T>
            bool operator()(T&& x, const AdsSymbol& y) const { return std::forward<T>(x) < y.symbol.shortName; }
            template <typename T>
            bool operator()(const AdsSymbol& x, T&& y) const { return x.symbol.shortName < std::forward<T>(y); }
            bool operator()(const AdsSymbol& x, const AdsSymbol& y) const { return x.symbol.shortName < y.symbol.shortName; }
            using is_transparent = int;
        };
        mutable set<AdsSymbol, SymbolCompare> _subSymbols;
    ...
        const AdsSymbol* FindSymbol(const string& name) const { return FindSymbol(string_view(name)); }
        const AdsSymbol* FindSymbol(string_view name) const
        {
            if (name == symbol.shortName)
                return this;
    
            if (symbol.shortName.size() <= name.size() || symbol.shortName == name.substr(0, symbol.shortName.size()) || name[symbol.shortName.size()] != '.')
                return nullptr;
    
             return FindSymbolImpl(substr(symbol.shortName.size()+1));
         }
         const AdsSymbol* FindSymbolImpl(stringview name) const
         {
             auto end = find(name.begin(), name.end(), '.');
             auto subSym = _subSymbols.find(name.substr(0, end));
             if (subSym == _subSymbols.end())
                 return nullptr;
             if (end == name.end())
                 return &*subSym;
             return subSym->FindSymbolImpl(name.substr(end+1));
         }
    };
    
    AdsSymbol tree_root;
    


  • @printee

    Ja ich versteh den Unterschied. Aber ich setzt die Namen nicht zusammen.
    In Name steht immer der gesamte Name drin. Also zusammengesetzt mit ".", Da mache ich nichts, das kommt direkt so von der SPS

    In shortName steht dann nur der eigene Name ohne die Namen der Eltern.

    Ich habe auch schon den shortName als key für die map verwendet und mal die FlattCollection für einen Test komplett weggelassen. Und der Speicher lief auch bis auf 2GB voll.



  • @camper

    1. Was dann? Klar ist der String dann doppelt vorhanden. Aber ich benötige den String ja als key

    2. Natürlich kann ich da einen Iterator schreiben der den Baum durchläuft. Das hatte ich ja schon geschreiben. Es war nur eine Frage der Effizienz ob ein Iterator schneller ist oder die Flatt halt einfach ab Programmstart aufzubauen.

    Aber wie gesagt. Die Flatt habe ich für einen Test weggelassen. Selber Speicherverbrauch.

    3. Siehe Antwort vorher. Wenn ich nur den shortName als Key nehme beliebt auch hier der Speicherverbrauch gleich hoch. In Name ist so schon der komplette Name drin.

    4. Danke für den Programmcode. Muss mir den erst mal genau anschauen. Aber wie gesagt mein Problem scheint nicht an den Pointern und an den zu langen strings gelagert zu sein.



  • Mir fällt gerade was anderes auf: Weiter vorn hast du geschrieben, es gibt insgesamt ungefähr eine Million Objekte (Symbols und Subsymbols). Wie passen die denn in die 3 MB, die von der SPS geholt werden? Das sind ja gerade mal 3 Bytes pro Objekt. Also, irgendwas stimmt hier nicht ...



  • @Printee du hast rech da passt was nicht.
    Aber ich weiß noch nicht was.

    Wenn ich mir den Speicher im Visual Studio (Process Memory) und im Taskmanager (Arbeitsspeicher privater Arbeitsatz) vor und nach dem Laden der Informationen aus der SPS anschaue. Steigt dieser in letzten Test sogar nur um 1 MB.



  • Vergiss das, was dir irgendwelche Taskmanager erzählen. Vor allem, wenn du den Verdacht hast, dass mit deinem Speicher irgendwas durcheinandergeht.

    Wenn dein Programm die SPS-Daten ausliest, dann muss es doch aufs Byte genau feststellen können, wie viele das sind. Ich verstehe ehrlich gesagt nicht, was daran so schwierig ist.



  • Vergiss das, was dir irgendwelche Taskmanager erzählen. Vor allem, wenn du den Verdacht hast, dass mit deinem Speicher irgendwas durcheinandergeht.

    Ja natürlich aber für einen grobe Aussage tuts der Taskmanager.
    Und 1 MB ist wie du schon sagtest ziemlich wenig.

    Ich verstehe ehrlich gesagt nicht, was daran so schwierig ist.

    Wer hat behauptet das dies schwierig ist? Habe da nun nur nicht gleich so genau hingeschaut. Ist ja nicht das eigentliche Problem.

    Aber für dich ganz genau. Der Speicher steigt um genau: 682,38 KB



  • booster schrieb:

    Vergiss das, was dir irgendwelche Taskmanager erzählen. Vor allem, wenn du den Verdacht hast, dass mit deinem Speicher irgendwas durcheinandergeht.

    Ja natürlich aber für einen grobe Aussage tuts der Taskmanager.

    Wenn du verstanden hast wie das mit den Heaps funktioniert, und auf die richtige Spalte im Task-Manager guckst (die unter Windows 10 z.B. per Default gar nicht angezeigt wird), dann schon. Sonst nicht.



  • Irgendwie wird es solangsam echt unübersichtlich:

    Deine Software benötigt, abhängig von CString oder std::String 1,2 oder 2 GB Arbeitsspeicher.
    Aber das Delta von vor einlesen und danach mit den aufgebauten Datenstrukturen hast du nur ein Unterschied von unter einem MB.
    Ist das so richtig? Dann suchen wir offensichtlich an der falschen Stelle nach deinem Speicherverbrauch...

    Was anderes, du hast irgendwo geschrieben, das du eine Exception bekommst. Bekommst du die, nachdem du die zyklischen shared pointer aufgelöst hast immer noch?



  • @hustbear
    Bin unter Windows 7 und hier ist die Spalte Arbeitsspeicher (privater Arbeitssatz) eingeblendet!

    @SchlangenMensch

    Aber das Delta von vor einlesen und danach mit den aufgebauten Datenstrukturen hast du nur ein Unterschied von unter einem MB.
    Ist das so richtig? Dann suchen wir offensichtlich an der falschen Stelle nach deinem Speicherverbrauch...

    Nein der unterschied von unter einem MB ist vor und nach dem lesen der Daten aus der SPS. Das hat ja Pintee gefragt. Das ist noch bevor die Datenstruktur aufgebaut ist.

    Was anderes, du hast irgendwo geschrieben, das du eine Exception bekommst. Bekommst du die, nachdem du die zyklischen shared pointer aufgelöst hast immer noch?

    Ja die exception kommt immer kanpp an der unteren Grenze zu 2GB speicher. Dann komm bad allocation. Ich habe die nun mal mit rohzeigern und mit weak pointern gemacht. Habe nun mal für einen Test auch die ganzen Beziehungen untereinader mal weg gelassen. Bring nichts.



  • booster schrieb:

    Ich verstehe ehrlich gesagt nicht, was daran so schwierig ist.

    Wer hat behauptet das dies schwierig ist? Habe da nun nur nicht gleich so genau hingeschaut. Ist ja nicht das eigentliche Problem.

    Doch, genau das ist das Problem. Dass du nicht so genau hinschaust. Dein Programm verballert gigabyteweise Speicher für quasi nichts (immer schon) und du wunderst dich nicht darüber. Wieso auch - läuft ja alles prächtig.

    Aber für dich ganz genau. Der Speicher steigt um genau: 682,38 KB

    Offenbar ist das doch zu schwierig. Ich hatte nicht gefragt, um wieviel irgendwelche Anzeigen steigen, sondern wie groß der Rohdatenblock ist, den deine Software aus der SPS liest.

    Und wenn die 682KB tatsächlich die gelesene Blockgröße wären, dann wären das rund 0,7 Byte pro Symbol - es ist wirklich erstaunlich, dass du solche Zahlen stumpf abschreibst, ohne dich im Mindesten darüber zu wundern. Gehörst du etwas auch zu denen, die bei all dem Kilo-Mega-Giga schon lange den Überblick verloren haben?



  • Kannst du uns vlt mal den Code zeigen, wo die Datenstruktur aufgebaut wird? Bei deinen Beschreibungen kann ich mir aktuell nicht vorstellen, wo der Speicher verbaucht wird.
    Als mir das letzte mal Speicher dermaßen explodiert ist, musste ich einzelne Bilder aus Videos bearbeiten. Hast du irgendwelche komprimierte Daten die du nach einlesen noch extrahierst?



  • @Pintee
    Wieso schon wieder so agressiv.

    Doch, genau das ist das Problem. Dass du nicht so genau hinschaust. Dein Programm verballert gigabyteweise Speicher für quasi nichts (immer schon) und du wunderst dich nicht darüber. Wieso auch - läuft ja alles prächtig.

    Natürlich habe ich beim Speicherverbrauch genau hingeschaut. Meine Güte. Ich habe nicht genau hingeschaut bei dem was direkt aus der SPS kam. Hier lag ja nicht der Fehler. Muss ich gleich die ganze Welt in Frage stellen irgendwo muss ich ja anfangen.

    Ich habe das Programm übernommen und versuche zu optimieren.

    Und wenn die 682KB tatsächlich die gelesene Blockgröße wären, dann wären das rund 0,7 Byte pro Symbol - es ist wirklich erstaunlich, dass du solche Zahlen stumpf abschreibst, ohne dich im Mindesten darüber zu wundern. Gehörst du etwas auch zu denen, die bei all dem Kilo-Mega-Giga schon lange den Überblick verloren haben?

    ?? Was soll das nun. Natürlich wundere ich mich darüber habe ich ja geschrieben, das da irgendwas seltsam ist.
    Die Zahl habe ich vom Memory Profiler. Natürlich kann ich nun auch die Anzahl der Bytes aus dem Block angeben. Da sind 691408 Bytes.

    Du wolltest den genauen Speicher haben und regst dich danach auf wenn ich ihn hier reintippe.

    Was hast du vor dich durch deine Aggression hier profilieren?



  • booster schrieb:

    Da sind 691408 Bytes.

    Und da sollen allen Ernstes Informationen über eine Million Objekte drin enthalten sein? Inklusive Namen wie "MyDings.MyBums.MyDingelings"? Völlig ausgeschlossen.

    Was hast du vor dich durch deine Aggression hier profilieren?

    Ich habs nicht nötig, mich zu profilieren. Und du darfst ab jetzt alleine weiterwurschteln.



  • Und da sollen allen Ernstes Informationen über eine Million Objekte drin enthalten sein? Inklusive Namen wie "MyDings.MyBums.MyDingelings"? Völlig ausgeschlossen.
    

    Das versuche ich gerade heraus zu finden.

    Ich habs nicht nötig, mich zu profilieren.

    Nicht, ok dann liegts daran dass du einfach gerne ausrastest.
    Ich lasse mir gerne helfen, und akzeptiere auch Kritik. Aber ich muss mir auch nicht alles gefallen lassen.



  • Wenn es interessiert:

    Hier ist der Link wie die Informationen aus der SPS gelesen werden.

    https://infosys.beckhoff.com/index.php?content=../content/1031/tcadsnetref/4018095371.html&id=





  • @TE
    Wenn dich jemand einen Ochsen nennt, dann hau ihm auf´s Maul.
    Wenn dich ein Zweiter einen Ochsen nennt, dann hau ihm auf´s Maul.
    Wenn dich ein Dritter einen Ochsen nennt wird´s Zeit einen Stall zu suchen.

    Merkst du nicht, dass du die Leute hier vergraulst? Seit 12 (!) Seiten ist immer noch nicht geklärt, was genau du eigentlich machst und wie deine Daten aussehen. Statt konkret zu liefern gibt´s ungenaue Beschreibungen und Salamitaktik, und wenn Anderen der Kragen platzt und einfach die Schnauze voll haben kommentierst du das mit Unverschämtheit und Profilierungssucht. So braun muss man erst mal sein...



  • Die 12 Seiten liegen vielleicht auch daran dass immer irgendwelche Seitenargumente daher kommen und ich alles mehrmals erklären muss.

    Ich habe immer Sachliche Argumente geliefert. Ich habe nie angegriffen. Immer erst dann als man mich beleidigt hat. Das nennt man Abwehr.

    Nur weil manchmal was falsch erklärt wurde muss man doch nicht ausfallend werden.


  • Mod

    booster schrieb:

    Sorry das war der falsche link.
    Hier ist der richtige:

    https://infosys.beckhoff.com/content/1031/tcsample_vc/html/tcadsdll_api_cpp_sample16.htm?id=3653485731247715096

    Grauenhaft. u.a. hat Der Author offenbar auch noch nie etwas von delete[] gehört. Dafür umso mehr virtual ohne Sinn und Verstand.

    Vermutlich solltest du nicht nach Speicher suchen, den deine Datenstruktur überflüssigerweise einnimmt, sondern nach Speicher, den du unterwegs verloren hast => alle new und delete durch geeignete Container ersetzen.


Anmelden zum Antworten