Speicherverbrauch shared_ptr und normaler *



  • Natürlich kannst du an der Datenstruktur was ändern. Du musst halt die Daten konvertieren.

    Summier doch mal die Größen der string-Nutzdaten auf und gib sie aus.

    map<string,unsigned long long> MemUsage;
    for( const auto& val : MapData )
    {
       MemUsage["comment"]   += (sizeof( string ) + val.comment.size);
       MemUsage["name"]      += (sizeof( string ) + val.name.size);
       MemUsage["shortname"] += (sizeof( string ) + val.shortname.size);
       MemUsage["type"]      += (sizeof( string ) + val.type.size);
    }
    

    Und jetzt guckste dir an, welche strings wie viel Speicher brauchen, dann haste nen Anhaltspunkt, wo du ansetzen kannst.



  • SeppJ weiß, wovon er spricht, und ich kann seine Reaktion durchaus nachvollziehen

    Das mag schon sein. Aber der Umgangs ton geht mal gar nicht. Man ist kein guter Moderator nur weil man sich im Bereich gut auskennt aber sich nicht unter Kontrolle hat.

    Ich habe hier nie beleidigt. Vielleicht hier und da mal etwas falsch gefragt oder falsch umschreiben. Nur weil ich nicht gleich alles offen legen wollte und der einfach halber manches zuerst weggelassen habe heißt das doch nicht dass ich mich nicht auskenne.

    Für die freiwillige Hilfe bin ich ja auch sehr dankbar. Aber so wie der seppl hier hat sich von den anderen keiner Verhalten.



  • booster schrieb:

    ...
    Und "type" ist nicht der eigentlich Datentyp. Der eigentliche Typ steht in Datatype. Da habe ich schon ein enum draus gemacht.
    ...

    Genau das ist der Punkt. Du zeigst uns Code, den du nicht benutzt, und wir sollen was dazu sagen 👎



  • booster schrieb:

    es handelt sich zum einen um eine struct
        struct ITcAdsSymbol
        {
            string			comment;
            string			name;
            string			shortName;
            string			type;
        };
    

    OK. Ein Kommentarfeld - das klingt nach potentiell sehr langen Strings, die aber nur sehr gelegentlich gebraucht werden. Lazy-loading nur bei Bedarf könnte hier ein Ausweg sein.

    Das Problem, booster, ist, dass du anfangs behauptet hast, du hättest nur raw-pointer durch shared_ptr ersetzt und damit wäre dein Speicherverbrauch von 1,2 auf über 2 GB explodiert.

    Später kam dann raus, deine Datenstruktur ist um einiges komplizierter als eingangs beschrieben (flache und tiefe Map) und du hast gleichzeitig mit dem Zeigerumbau auch CString durch std::string ersetzt. Inzwischen sind wir auf der 8. Seite und noch nicht wirklich weiter, weil scheibchenweise immer neue Details bekannt werden. Dass so mancher da die Geduld verliert, ist vielleicht nachvollziehbar.



  • @DocShoe

    Du zeigst uns Code, den du nicht benutzt, und wir sollen was dazu sagen

    Was soll das jetzt? Ich habe doch die Struktur gezeigt. Der Datentyp steht doch ganz oben:

    AdsDatatypeId   datatype
    

    Ich habe doch gar nicht gesagt dass ich den typ nicht nutze. In "type" steht auch ein Name drin. Dass die den typ genannt haben ist ja jetzt sicher keine Ursache für das Speicherproblem!

    Natürlich kannst du an der Datenstruktur was ändern. Du musst halt die Daten konvertieren.

    Wieso sollte ich? Es macht doch keinen Sinn einen long in einen unsigned short zu konvertieren.



  • Ächz

    Einmal nicht, vier Millionen mal vielleicht schon.



  • @Printe
    an das Kommentar Feld habe ich auch schon gedacht und erst mal aus kommentiert aber hat auch noch nicht viel gebracht.

    Gut dass ich anfangs gesagt habe dass ich nur die pointer Geschichte umgebaut habe lag daran dass ich an den string schlicht nicht mehr gedacht habe.

    Und das mit der Flachen bzw Baumstruktur habe ich nicht erwähnt da ich daran ja nichts geändert habe. Die Baum + Flache Strukur war ja vorher schon vorhanden.

    Man soll ja versuchen das Problem so weit wie möglich einzukreisen bevor man nachfragt.



  • 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.


Anmelden zum Antworten