Speicherverbrauch shared_ptr und normaler *



  • Jetzt mal was ganz Anderes:
    Brauchst du wirklich 1.000.000 Objekte gleichzeitig im Speicher? Reicht es nicht aus, nur relevante Daten im Speicher zu halten und bei Bedarf nachzuladen? Woher kommen denn die Daten und wie schnell kannst du auf die Originaldaten zugreifen/nachladen?



  • Ächz

    Einmal nicht, vier Millionen mal vielleicht schon.

    ????????????

    Ein Wert von IndexOffset ist z.B. 3032838

    Wie soll ich das nun in einen unsigned shor umwandeln.

    Genau das ist doch der Punkt wieso ich meine Struktur nicht offen legen wollte.
    Liegt es jetzt an dem long oder short wieso ich einen erhöhten Speicherverbrauch von 800MB habe. Und das noch dazu dass es vorher ein long war und danach immer noch ein long ist.



  • Brauchst du wirklich 1.000.000 Objekte gleichzeitig im Speicher

    Ich brauche die Daten beim Start der Applikation. Ich lade alle Informationen in den Speicher. Damit ich dieser zu Erzeugung anderer Objekte zur Verfügung habe. Danach kann man den Speicher wieder aufräumen.

    Natürlich könnte man anfangs nur mal z.B. nur den "Namen" des Objekts in den Speicher laden und nachher nur von den wirklich benötigten Objekten den Rest.

    Aber das laden aus der SPS ist nicht sehr performant. Darum war die bisher die Lösung alles bei Start zu laden.



  • booster schrieb:

    Genau das ist doch der Punkt wieso ich meine Struktur nicht offen legen wollte.
    Liegt es jetzt an dem long oder short wieso ich einen erhöhten Speicherverbrauch von 800MB habe. Und das noch dazu dass es vorher ein long war und danach immer noch ein long ist.

    Achso. Und ich dachte schon, wir wollten den Gesamtspeicherverbrauch senken, um mehr Platz für die Nutzdaten zu haben. Zugegebenermaßen sind 8 MB bei 800 MB nur 1%, aber weiß der Geier, wieviele Instanzen von ITcAdsSymbol es tatsächlich gibt.

    Habe dein Programm so richtig verstanden:

    1. Einlesen der Daten aus der SPS
    2. Erzeugen von anderen Daten aus den SPS-Daten
    3. Löschen der SPS-Daten aus dem Speicher

    ?



  • @DocShoe

    Erst mal ging es mir den erhöhten Speicherverbrauch zu erklären. Deshalb habe ich meine Erklärung auf das wichtigste reduziert. Und das war zunächst der pointer dann um den string.

    Klar wäre es dann schön auch den Gesamtverbrauch zu senken. Aber ich denke wenn wir wissen woher der erhöhte Speicherverbrauch herkommt lässt sich auch der Gesamtverbrauch erklären.

    Und da versteh ich es nicht wieso man Dinge wie den typ anmeckert nur weil ich den nicht erklärt habe. Oder wieso man nun aus nem long einen short machen will obwohl hier der Wert den range des short übersteigt.

    Habe dein Programm so richtig verstanden:

    1. Einlesen der Daten aus der SPS
    2. Erzeugen von anderen Daten aus den SPS-Daten
    3. Löschen der SPS-Daten aus dem Speicher

    Ja so der Teilabschnitt im Programm um den es sich gerade dreht.

    Aber nochmals kann es vielleicht sein dass der Speicherverbrauch daher rührt dass die Objekte wiederum selbst eine Map mit string als key haben?



  • Die Schlüssel sind wohl für alle Objekte in der map die Gleichen - ohne Verwaltung wird also für immer die gleichen Schlüssel jeweils neuer Speicher belegt.
    Das wurde dir aber schon mehr als ein Mal gesagt...

    [solved]

    PS: Du schreibst, die Zielrechner wären mit XP ausgestattet, können wohl gut und gerne als alt bezeichnet werden - und nun möchtest du aus „Performancegründen” alles beim Start in den Speicher laden, obwohl es ungewiss und unwahrscheinlich ist, dass diese Rechner überhaupt so viel physischen Hauptspeicher haben...

    Meine Meinug zu dem Thread: lol



  • Die Schlüssel sind wohl für alle Objekte in der map die Gleichen - ohne Verwaltung wird also für immer die gleichen Schlüssel jeweils neuer Speicher belegt.
    Das wurde dir aber schon mehr als ein Mal gesagt...

    Wieso??

    Es sind doch nicht die gleichen Schlüssel. Warum auch.

    PS: Du schreibst, die Zielrechner wären mit XP ausgestattet, können wohl gut und gerne als alt bezeichnet werden - und nun möchtest du aus „Performancegründen” alles beim Start in den Speicher laden, obwohl es ungewiss und unwahrscheinlich ist, dass diese Rechner überhaupt so viel physischen Hauptspeicher haben...

    Was soll das den nun. Bisher wurde 1,2Gb in den Speicher geladen das hat ausgereicht. Wieso soll das nun ungewiss sein.

    Du kennst doch gar nicht die Performance wenn ich immer Stcück für Stück lade!

    Meine Meinug zu dem Beitrag: troll.



  • booster schrieb:

    Aber das laden aus der SPS ist nicht sehr performant. Darum war die bisher die Lösung alles bei Start zu laden.

    Wieviele Daten kommen denn aus der SPS? Das sind doch keine Gigabytes? Das bläht sich doch erst in deinem Programm so auf, oder? Das wär doch mal ein wichtiger Hinweis, mit welcher Datenmenge wir es hier überhaupt zu tun haben.

    Aber nochmals kann es vielleicht sein dass der Speicherverbrauch daher rührt dass die Objekte wiederum selbst eine Map mit string als key haben?

    Ich dachte, das hier wäre das Objekt:

    struct ITcAdsSymbol
        {
            string          comment;
            AdsDatatypeId           datatype;  //enum
            long            indexGroup;
            long            indexOffset;
            string          name;
            string          shortName;
            int             size;
            int             subSymbolCount;
            string          type;
        };
    

    Wo ist denn da eine Map? Was für Objekte mappt die, und wie viele?

    Erst mal ging es mir den erhöhten Speicherverbrauch zu erklären. Deshalb habe ich meine Erklärung auf das wichtigste reduziert. Und das war zunächst der pointer dann um den string.

    Ja, aber wir hatten relativ schnell heraus, dass das allein nicht der Grund sein kann. Und wenn das klar ist, dann muss man anfangen, das Ganze zu betrachten.

    Dass du kein vollständiges Projekt posten darfst und willst, versteht sich.



  • Und das Rätselraten geht weiter...

    JA, es kann sein, dass strings als Schlüssel viel Speicher verbrauchen. Wissen wir aber nicht, weil wir keine Ahnung haben, wie du die maps befüllst und wie viele verschiedene Schlüssel es gibt.
    Am besten baust du dir wirklich ein Diagnosetool, dass deine strings und deren Speicherverbrauch zählt. Oder du bemühst einen Profiler, der das für dich erledigt. Wenn du dann herausgefunden hast, ob es dann an string und dessen Verwendung als Schlüssel in einer map liegt kannst du dir Optimierungen einfallen lassen.

    Und was fdfs Hinweis angeht:
    Es ist nicht von der Hand zu weisen, dass du da eine schmale Gratwanderung machst. Bisher hat alles in den Speicher gepasst, aber du hast nur einen Datentyp durch einen anderen ersetzt und schon fliegt dir alles um die Ohren. Was passiert denn, wenn ein anderer SPS Typ zum Einsatz kommt, der mehr Daten produziert (falls der Fall eintreten kann, oder unterstützt die Software nur genau einen SPS Typen)?
    In einem 32bit Prozess 1.2GB Daten verwalten kann zu einem Glücksspiel werden, du hast für den gesamten Prozess unter Windows lediglich 2GB. Langfristig solltest du dir was anderes überlegen.



  • @printee

    und um eine Klasse die zum einen eine Referenz auf die struct hat. Desweiteren eine map die wiederum die Kinder darstellen. Objekte der selben Klasse.

    hatte ich geschrieben.

    @DocShoe

    JA, es kann sein, dass strings als Schlüssel viel Speicher verbrauchen. Wissen wir aber nicht, weil wir keine Ahnung haben, wie du die maps befüllst und wie
    viele verschiedene Schlüssel es gibt.

    Die keys sind die Variablenamen der SPS. Und da gibt es so viele Keys wie variablen und das sind nun mal über eine Million.

    Und das Rätselraten geht weiter...
    Wieso den. Ihr bringt immer wieder Nebenaspekte z.B. das was fdfs sagt. Natürlich ist das ein Problem. Aber ich will jetzt erst mal den mehr Speicherverbrauch klären.

    Was soll ich machen mein ganzes Programm posten und einfach sagen optimiert mal?



  • Benötigst du denn wirklich die komplette std::string-Funktionalität? Reicht nicht evtl. einfach ein const char* oder ein schmaler Wrapper (wie in Implementation of cstring wrapper class diskutiert)? Damit hast du dann den selben Memory-Footprint (basierend auf dem originalen CString).
    Und mittels eines typedef kannst du dann einfach (zum Vergleich) die String-Implementierung austauschen.



  • booster schrieb:

    @printee

    und um eine Klasse die zum einen eine Referenz auf die struct hat. Desweiteren eine map die wiederum die Kinder darstellen. Objekte der selben Klasse.

    hatte ich geschrieben.

    Ja, stimmt. Ein Bröckchen Information, das im Getöse untergegangen ist. Ein hingeworfener halber Satz wird nun mal leicht übersehen. Was lernen wir draus? Geduldig bei der Sache bleiben, Kritik ernst nehmen, Streit aus dem Weg gehen und die Informationen besser aufbereiten. Du bist es, der hier Hilfe will, vergiss das nicht.

    Ist es also so?

    struct ITcAdsSymbol
    {
    	//	struct-Members wie oben
    };
    
    class MyClass
    {
    	ITcAdsSymbol & symbol;
    
    	std::map<std::string, MyClass> children;
    };
    
    //	irgendwo ein systemweites Map-Objekt
    std::map<std::string, MyClass> parents;
    

    Was soll ich machen mein ganzes Programm posten und einfach sagen optimiert mal?

    Nein, denn das ist dein Job, nicht unserer.



  • booster schrieb:

    Die keys sind die Variablenamen der SPS. Und da gibt es so viele Keys wie variablen und das sind nun mal über eine Million.

    Sind die Variablen der SPS nummeriert oder bestehen sie nur aus dem Namen? Kannst du eine Lookup-Tabelle bauen, die den Namen zu einer ID liefert? Dann kannst du von std::map<std::string,ITcAdsSymbol> zu std::map<unsigned int,ITcAdsSymbol> wechseln, um doppelte strings zu vermeiden. Und wenn du den Namen einer Variablen brauchst suchst du ihn in der LUT.



  • Und verrat bitte endlich, wieviel Bytes Daten ursprünglich aus der SPS geholt werden. Damit man einschätzen kann, wieviel von diesen 1,2 GB echte Information ist und wieviel Redundanz.



  • DocShoe schrieb:

    Die Pragma Anweisung verhindert Padding, was zu kleineren Strukturgröße führt, aber den Zugriff auf die Member etwas verlangsamt.

    Auf den meisten Plattformen ist es von der Performance her quasi Wurst. Auf SPARC ist #pragma pack(1) die Hölle (tm).



  • Nein, denn das ist dein Job, nicht unserer.

    Also dann kann ich ja nur das Posten was ich im ersten Moment für richtig halte bzw. das worauf sich meine Konkrete Frage bezieht.

    Man wirft mir vor das ich zuwenig Informationen heraus gebe. Was sind zu wenig was sind zu viel?

    Und ich versuche sachlich zu bleiben, aber der seppl wirft mir ja immer wieder hin dass mein Datenmodel nicht passt nur weil ich nicht alles komplet offen gelegt habe.

    Und ich nehme Krtik ernst. Nur Beleidiguungen und pauschale Aussagen nehme ich nicht ernst.

    Und verrat bitte endlich, wieviel Bytes Daten ursprünglich aus der SPS geholt werden. Damit man einschätzen kann, wieviel von diesen 1,2 GB echte Information ist und wieviel Redundanz.

    Also die Daten der SPS sind wirklich sehr wenig. 3MB um genau zu sein.
    Das Problem ist der Objektbaum.

    Und der sieht im Prinzip so aus wie printe gezeigt hat.

    nur dass ich um die map nochmals ne wrapper Klasse gemacht habe in der ich die Findmethode implementiert habe,

    struct ITcAdsSymbol
    {
        //  struct-Members wie oben
    };
    
    class AdsSymbol
    {
        ITcAdsSymbol & symbol;
    
        shared_ptr<InfoCollection> _subsymbols;
    };
    
    class InfoCollection
    {
       map<string, shared_ptr<AdsSymbol>> _infoMap;
    
       shared_ptr<AdsSymbol> FindSymbol(const string& name) const
       {
           const auto pos = _infoMap.find(name);
           if (pos != _infoMap.end())
           {
               return pos->second;
           }
    
            for (const auto& info : _infoMap)
            {
                const auto symbol = info.second->SubSymbols->FindSymbol(name);
                if (symbol != nullptr)
                {
                    return symbol;
                }
            }
    
            return nullptr;
        }
    }
    
    //  das  erwähnte "systemweite Map-Objekt" ist in der Klasse Loader hinterlegt.
    // bzw es sind ja wie gesagt 2 collections. Flach und Baum.
    
    [code="cpp"]/// SymbolInfo Collection als Baum Struktur
    shared_ptr<InfoCollection> _treeCollection;
    
    /// SymbolInfo Collection als Flache Struktur
    shared_ptr<InfoCollection> _flatCollection;
    

    [/code]

    Der ganze Speicher wird natürlich verbraucht bei der Aufbereitung der Daten der SPS in die genannte Struktur.



  • Also wenn 3MB auf 1.2GB aufgebläht werden gibt es da sicher Optimierungspotenzial.

    Wie viele Elemente hat denn so eine map? Sind das eher 10 oder eher 100? Du hast ja schon bemerkt, dass die map overhead hat. Wenn ich dich richtig verstanden habe brauchst du die Daten nur zum Aufbauen anderer Daten, sie sind also read-only. Statt einer map könntest du auch einen sortierten vector nehmen und mit binärer Suche suchen, dann hast du einen vector mit wenig Overhead und trotzdem schnellen Zugriff. Auf smart pointer könntest du dann ebenfalls komplett verzichten und die Kindbäume mit rohen Zeigern befüllen. Das sollte einiges bringen.



  • Na also, endlich kommen die interessanten Informationen. Jetzt hab ich noch ein paar Verständnisfragen:

    1. Was verwendest du als Key? Das, was in ITcAdsSymbol::name steht?
    2. Der Unterschied zwischen der flatCollection und der treeCollection ist was genau? Das hast du bestimmt schon mal irgendwo erwähnt, aber vielleicht kannst du es, mit den Deklarationen vor der Nase, nochmal kurz auf den Punkt bringen?
    3. Ist jedes Symbol und jedes Subsymbol genau einmal in den Collections? Oder sind die mehrfach vorhanden? Wenn ja, nach welchen Regeln?
    4. AdsSymbol enthält eine Referenz auf ein ITcAdsSymbol-struct. Warum ist das eine Referenz, und wo befinden sich die tatsächlichen Struct-Daten? Die fehlen uns nämlich noch.



  • Hallo Printe

    1. Ja

    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.

    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"

    4. Schreibfehler ist keine Referenz. Sorry das & ist zu viel.



  • booster schrieb:

    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"

    Kommen denn diese zusammengesetzten Namen original aus der SPS? Oder bildest du die in der Software, indem du auf jedem Weg durch den Baum die Namen aufsammelst und hintereinanderstellst?

    Verstehst du den Unterschied?

    Im zweiten Fall bildest du selber Namen wie "MyFunctionBlock.MyStruct.MyDings", "MyFunctionBlock.MyStruct.MyBums", "MyFunctionBlock.MyStruct.MyBlah" usw., die es in den Originaldaten so nicht gibt. Der Teil "MyFunctionBlock.MyStruct" wird dabei immer wieder dupliziert. Das bläht den Speicherbedarf schon merklich auf ...

    Außerdem hast du wegen flat und tree schon mal alles doppelt.


Anmelden zum Antworten