Autor |
Beitrag |
Sy-
      
Beiträge: 177
|
Verfasst: Do 01.02.07 11:15
Hi all,
habe hier in einem Thread ein IDHttp welches ständig Seiten abruft.
Kann mir einer Verraten warum dieser Abschnitt mir die ganze Zeit Speicher Frisst?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| html:string; ...
try html:=http.Get(url); except result:=-1; exit; end; |
die komponente wird immer wieder neu erstellt und jeweils natürlich auch .free und :=nil
Grüße
_________________ Problems connecting People
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 01.02.07 11:25
Hmm, sollte zwar eigentlich nicht notwendig sein, aber du kannst ja mal versuchen mit html := ''; den String explizit zu leeren.
Das Get wird den Speicher jedenfalls wohl nicht behalten, aber das kannst du ja testen indem du nur Get aufrufst ohne das Ergebnis in den String zu packen. Ich nehme mal an, dass dann die Speicherauslastung nicht zunimmt.
Was passiert ist ja: Der Speicher wird belegt, und dann hast du in html einen Pointer darauf. Sobald du html aber wieder einem neuen String (aus Get) zuweist, sollte eigentlich der Referenzzähler des Strings auf 0 gehen und der String im Speicher freigegeben werden.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 01.02.07 12:10
Moin!
Ich habe auch schonmal Erfahrung mit komischen Effekten bei dynamischen Variablen in Threads gemacht...  Das Thema scheint sehr viel komplexer zu sein, als es aussieht.
Zum einen hier mal was aus der DOH dazu:
Delphi-Online-Hilfe hat folgendes geschrieben: | Thread-Variablen (oder Thread-lokale Variablen) finden in Multithread-Anwendungen Verwendung. Eine Thread-Variable entspricht in etwa einer globalen Variablen, die einzelnen Ausführungs-Threads erhalten jedoch eine eigene, private Kopie der Variablen, auf die andere Threads keinen Zugriff haben. Thread-Variablen werden nicht mit var, sondern mit threadvar deklariert. Ein Beispiel:
threadvar X: Integer;
Die Deklaration einer Thread-Variablen
darf nicht innerhalb einer Prozedur oder Funktion erfolgen.
darf keine Initialisierungen enthalten.
darf nicht die Direktive absolute enthalten.
Dynamische Variablen, die normalerweise vom Compiler verwaltet werden (lange Strings, Strings des Typs WideString, dynamische Arrays, Varianten und Schnittstellen), können mit der Direktive threadvar deklariert werden. Der Compiler gibt aber den auf dem Heap belegten Speicher (der von den einzelnen Ausführungs-Threads reserviert wird) nicht automatisch frei. Wenn Sie diese Datentypen in Thread-Variablen verwenden, müssen Sie selbst für die Freigabe des Speichers innerhalb des Threads sorgen, bevor dieser beendet wird. Ein Beispiel:
threadvar S: AnsiString;
S := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
...
S := ''; // Den von S belegten Speicher freigeben
Hinweis
Die Verwendung solcher Konstrukte wird nicht empfohlen.
Sie können Varianten freigeben, indem Sie ihnen den Status Unassigned zuweisen. Um Schnittstellen oder dynamische Arrays freizugeben, weisen Sie ihnen den Wert nil zu.) |
Und dann gibt es noch diverse spannende Dinge, die man darüber nachlesen kann DELPHI THREAD HEAP
Weiterhin scheint es deutlich besser zu sein, wenn man direkt "speicheroptimiert" konzeptioniert. In deinem Fall:
- Wenn der Thread regelmäßig Dinge tut, dann ist es sehr sinnvoll, die Aufgabe als Schleife im Thread zu organisieren und eine geeignete Signalisierung zu verwenden, als immer wieder einen Thread anzustarten, der dann die Aufgabe nur einmal ausführt.
- Es ist sicher nicht sinnvoll, immer wieder den TIdHttp neu zu erstellen, wenn du die Kompo sowieso nochmal brauchst.
- Wenn du einen langen String (allg. dyn. Objekte) in einem Thread nicht mehr brauchst, gib ihn immer selbst wieder frei (geeignete Methoden s. DOH).
- Versuche möglichst, benötigten Speicher als "ausreichend großen" Block im Thread anzufordern und für die Aufgaben zu recyclen, um damit dem DMM die Aufgabe abzunehmen, die Blöcke intern wiederverwendbar zu machen (das kann der nämlisch scheinbar nicht besonders gut...
)
Fazit: Threads und dynamische Variablen mit dem Delpih-MM sind ein ziemlich komplexes Thema.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 01.02.07 12:17
Gilt das nicht nur, wenn man die Variablen auch mit threadvar deklariert? Das ist doch was anderes. Ich meine, solange der Thread nur einmal läuft, braucht mal die ja auch nicht, dann kann man ja normale globale Variablen nutzen. Schwierig wird das ja erst, wenn der Thread mehrfach läuft. Erst da kommen ja Thread-Variablen ins Spiel.
Dass dies zur Informationsweitergabe aus einem Thread nur bedingt tauglich ist, ist noch ne ganz andere Sache...
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 01.02.07 13:31
Moin!
jaenicke hat folgendes geschrieben: | Gilt das nicht nur, wenn man die Variablen auch mit threadvar deklariert? |
Klar, war auch nur für den Fall von mir zitiert, dass es verwendet wird.
jaenicke hat folgendes geschrieben: | Das ist doch was anderes. Ich meine, solange der Thread nur einmal läuft, braucht mal die ja auch nicht, dann kann man ja normale globale Variablen nutzen. Schwierig wird das ja erst, wenn der Thread mehrfach läuft. Erst da kommen ja Thread-Variablen ins Spiel. |
Nun, du kannst auch bei mehrfacher Ausführung eines Threads mit lokalen Variablen des Thread-Objekts (TThread-Descendants) arbeiten. Globale Variablen für Threads scheinen mir allerdings generell NIE eine gute Idee zu sein...
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|