Speicherverbrauch shared_ptr und normaler *
-
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!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=
-
Sorry das war der falsche link.
Hier ist der richtige:
-
@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.
-
booster schrieb:
Sorry das war der falsche link.
Hier ist der richtige: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.
-
@camper
ja das mit dem delete[] habe ich auch bemerkt. Dies habe ich bei mir im Code aber richtig gestellt. An dem liegt es nicht.Grauenhaft? Was meinst du genau ausser den falschen delete.
-
Gut wenn man sich das Beispiel runter lädt und die Klasse CAdsParseSymbols anschaut dann kann man grauenhaft sagen.
-
Das ist aber doch nicht der Code den du verwendest, oder? Zumindest finde ich keine Stelle, wo irgendwelche Maps befüllt werden oder ähnliches.
-
Das ist der Code den ich verwende um die Informationen aus der SPS auszuelesen.
Mit Hilfe dieser Informationen baue ich dann meine Flat- und TreeCollection auf.
-
Das ist der Code dazu
void TcAdsSymbolInfoLoader::CreateCollection(const shared_ptr<AdsParseSymbols>& parseSymbols, shared_ptr<TcAdsSymbolInfoCollection>& treeCollection, shared_ptr<TcAdsSymbolInfoCollection>& flatCollection) const { if (!parseSymbols) { const auto message = FTRANSLATE("Invalid argument '{1}'.", "parseSymbols"); THROW_TRACEABLE_EXCEPTION(message); } treeCollection = make_shared<TcAdsSymbolInfoCollection>(); flatCollection = make_shared<TcAdsSymbolInfoCollection>(); AdsSymbolInfo main; weak_ptr<TcAdsSymbolInfo> tclast; const auto symbolCount = parseSymbols->SymbolCount(); for(unsigned int i=0; i < symbolCount; i++) { auto tcmain = make_shared<TcAdsSymbolInfo>(); // next symbol für das vorherige setzen if( i != 0 ) { tclast.lock()->_nextSymbol = tcmain; } parseSymbols->Symbol(i,main); const auto subsymbolCount = CreateSubSymbols(parseSymbols,main,tcmain); tcmain->AssignAdsSymbolInfo(main,subsymbolCount); flatCollection->Add(tcmain); treeCollection->Add(tcmain); // Symbol abspeichern für Zeiger auf letztes Element tclast = tcmain; } } int TcAdsSymbolInfoLoader::CreateSubSymbols(const shared_ptr<AdsParseSymbols>& parseSymbols, AdsSymbolInfo& parent, const shared_ptr<TcAdsSymbolInfo>& tcparent) const { AdsSymbolInfo subinfo; weak_ptr<TcAdsSymbolInfo> tclast; const auto pDataType = parseSymbols->GetTypeByName(parent.type); const auto subSymbolCount = parseSymbols->SubSymbolCount(pDataType); for (unsigned int i = 0; i < subSymbolCount; i++) { auto tcsubinfo = make_shared<TcAdsSymbolInfo>(); //auto tcsubinfo = new TcAdsSymbolInfo(); // next symbol für das vorherige setzen if (i != 0) tclast.lock()->_nextSymbol = tcsubinfo; // erstes Subsymbol für parent setzen else tcparent->_firstSubSymbol = tcsubinfo; parseSymbols->SubSymbolInfo(parent, i, subinfo); // Symbol abspeichern für Zeiger auf letztes Element tclast = tcsubinfo; // Parent setzen tcsubinfo->_parent = tcparent; // SubSymbols rekursiv aufrufen const auto count = CreateSubSymbols(parseSymbols, subinfo, tcsubinfo); tcsubinfo->AssignAdsSymbolInfo(subinfo, count); _flatCollection->Add(tcsubinfo); tcparent->_subSymbols->Add(tcsubinfo); } return subSymbolCount; }
-
Welchen Typ hat TcAdsSymbolInfo::_parent?
-
TcAdsSymbolInfo::_parent ist aktuell vom typ weak_ptr<TcAdsSymbolInfo>.
TcAdsSymbolInfo ist eigentlich nur eine wrapper klasse um AdsSymbolInfo
die ich dann in meinen Collections abspeichereclass TcAdsSymbolInfo { /// Zeiger auf erstes Symbol weak_ptr<TcAdsSymbolInfo> _firstSubSymbol; /// Zeiger auf nächstes Symbol weak_ptr<TcAdsSymbolInfo> _nextSymbol; /// Zeiger auf Elternsymbol weak_ptr<TcAdsSymbolInfo> _parent; /// Zeiger auf Untersymbole shared_ptr<TcAdsSymbolInfoCollection> _subSymbols; /// Struktur mit Basisinformationen ITcAdsSymbol _baseInfos; void AssignAdsSymbolInfo(AdsSymbolInfo &info, const int subSymbolCount ) { _baseInfos.comment = info.comment; _baseInfos.datatype = AdsDatatypeId::_from_integral(info.dataType); _baseInfos.indexGroup = info.iGrp; _baseInfos.indexOffset = info.iOffs; _baseInfos.name = info.fullname; _baseInfos.shortName = info.name; _baseInfos.size = info.size; _baseInfos.type = info.type; _baseInfos.subSymbolCount = subSymbolCount; } }
-
Schau dir nochmal das Beispiel von weak_ptr hier an http://en.cppreference.com/w/cpp/memory/weak_ptr
std::weak_ptr<int> gw; void observe() { std::cout << "use_count == " << gw.use_count() << ": "; if (auto spt = gw.lock()) { // Has to be copied into a shared_ptr before usage std::cout << *spt << "\n"; } else { std::cout << "gw is expired\n"; } } int main() { { auto sp = std::make_shared<int>(42); gw = sp; observe(); } observe(); }
Du läufst genau in die Falle, du erstellst mit make_shared in Zeile 59 einen shared ptr und weißt den in Zeile 64 oder 67 einem weak_ptr zu. Wenn der shared_ptr jetzt out of scope geht, ist der weak_ptr auch ungültig.