![]() |
Mein Programm ist Arbeitsspeicher hungrig..
Hey,
ich habe eine TList mit ca. 41.000 Einträgen. Jeder dieser Einträge besteht aus 12 Booleans und einem String (maximal 5 Zeichen). Und genau hier entsteht mein Problem. Ich speichere die Daten total hässlich im Textformal ab (bsp: Toll;1;0;1;0;1;0;..). Die Datei ist gerade mal ~1MB groß. Wird das ganze aber in den Arbeitsspeicher geladen, nimmt es riesige Ausmaße an und ist 100MB groß. Woran liegt das denn bitte? |
AW: Mein Programm ist Arbeitsspeicher hungrig..
Wie sieht die Datenstruktur eines Eintrages aus?
|
AW: Mein Programm ist Arbeitsspeicher hungrig..
Zitat:
Ich darf auch mal :stupid:. Ne, mal im Ernst: Ohne Code und die Kenntnis der Datenstruktur wird da keiner etwas dazu sagen können. MfG Dalai |
AW: Mein Programm ist Arbeitsspeicher hungrig..
Achso klar, dachte das reicht:
Delphi-Quellcode:
IDListEx: TList<TTeUpdateDBIDState>;
und TTeUpdateDBIDState = record id: String; AccountBindOnUse: Boolean; AccountBound: Boolean; HideSuffix: Boolean; MonsterOnly: Boolean; NoMysticForge: Boolean; NoSalvage: Boolean; NoSell: Boolean; NotUpgradeable: Boolean; NoUnderwater: Boolean; SoulbindOnAcquire: Boolean; SoulBindOnUse: Boolean; Unique: Boolean; end; wobei der String zwischen 1 und 5 Zeichen schwankt, aber nie größer ist. Die Liste wird dann während der Laufzeit gefüllt und hat am and ~41.000 Einträge was 100MB Arbeitsspeicher bedeutet |
AW: Mein Programm ist Arbeitsspeicher hungrig..
Und wie genau liest du die Daten ein?
MfG Dalai |
AW: Mein Programm ist Arbeitsspeicher hungrig..
Kann ich nicht nachvollziehen
Delphi-Quellcode:
program dp_185142;
{$APPTYPE CONSOLE} {$R *.res} uses System.Generics.Collections, System.SysUtils; type TTeUpdateDBIDState = record id: string; AccountBindOnUse: Boolean; AccountBound: Boolean; HideSuffix: Boolean; MonsterOnly: Boolean; NoMysticForge: Boolean; NoSalvage: Boolean; NoSell: Boolean; NotUpgradeable: Boolean; NoUnderwater: Boolean; SoulbindOnAcquire: Boolean; SoulBindOnUse: Boolean; Unique: Boolean; end; procedure Test; var IDListEx: TList<TTeUpdateDBIDState>; LItem: TTeUpdateDBIDState; begin // TaskManager -> 588KB IDListEx := TList<TTeUpdateDBIDState>.Create; try while IDListEx.Count < 41000 do begin LItem.id := ( IDListEx.Count + 1 ).ToString; IDListEx.Add( LItem ); end; finally // TaskManager -> 2892KB IDListEx.Free; end; end; begin try Test; except on E: Exception do Writeln( E.ClassName, ': ', E.Message ); end; // TaskManager -> 1864KB ReadLn; end. |
AW: Mein Programm ist Arbeitsspeicher hungrig..
Okay bin ratlos. Da habt ihr meinen Code..
Delphi-Quellcode:
Aufgerufen wird die GetIDInformation-Funktion..
unit TeUpdateDB;
interface uses System.Generics.Collections,IdHTTP, System.Threading, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, System.Classes; type TTeUpdateDBStatus = record id: Integer; current,max: Integer; end; TTeUpdateDBIDState = record id: String; AccountBindOnUse: Boolean; AccountBound: Boolean; HideSuffix: Boolean; MonsterOnly: Boolean; NoMysticForge: Boolean; NoSalvage: Boolean; NoSell: Boolean; NotUpgradeable: Boolean; NoUnderwater: Boolean; SoulbindOnAcquire: Boolean; SoulBindOnUse: Boolean; Unique: Boolean; end; type TTeUpdateDB = class(TObject) private IDList: TStringList; IDListEx: TList<TTeUpdateDBIDState>; IDListTask: ITask; procedure AddToIDListEx(sl: TStringList;fstart,fend:Integer); procedure BuiltIDList; procedure BuiltIDListEx(fstart, fend: Integer); function CountEntries(s: String): Integer; procedure SplitEntries(sl: TStringList; s: String); function BToStr(b:Boolean): String; public state: TTeUpdateDBStatus; constructor Create; procedure GetIDInformation; procedure SaveIDListEx(p: String); end; implementation uses System.SysUtils, Vcl.Dialogs; const maxidrequ = 200; constructor TTeUpdateDB.Create; begin IDList := TStringList.Create; IDListEx := TList<TTeUpdateDBIDState>.Create; state.id := -2; end; procedure TTeUpdateDB.GetIDInformation; begin IDListTask := TTask.Create(procedure() var max,fstart,fend: Integer; begin BuiltIDList; //debugging state.id := 0; max := IDList.Count -1; state.max := max; fstart := 0; fend := -1; IDListEx.Clear; while fend <> max do begin fstart := fend + 1; fend := fstart + (maxidrequ-1); state.current := fstart; if fend > max then fend := max; if fstart > fend then break; BuiltIDListEx(fstart,fend); end; //debugging SaveIDListEx('test.dat'); end); IDListTask.Start; end; procedure TTeUpdateDB.SaveIDListEx(p: string); var sl:TStringList; i: Integer; begin sl := TStringList.Create; for i := 0 to IDListEx.Count-1 do begin sl.Add(IDListEx[i].id + ';' + BToStr(IDListEx[i].AccountBindOnUse) + ';' + BToStr(IDListEx[i].AccountBound) + ';' + BToStr(IDListEx[i].HideSuffix) + ';' + BToStr(IDListEx[i].MonsterOnly) + ';' + BToStr(IDListEx[i].NoMysticForge) + ';' + BToStr(IDListEx[i].NoSalvage) + ';' + BToStr(IDListEx[i].NoSell) + ';' + BToStr(IDListEx[i].NotUpgradeable) + ';' + BToStr(IDListEx[i].NoUnderwater) + ';' + BToStr(IDListEx[i].SoulbindOnAcquire) + ';' + BToStr(IDListEx[i].SoulBindOnUse) + ';' + BToStr(IDListEx[i].Unique)); end; sl.SaveToFile(p,TEncoding.UTF8); end; //########################################################################################################### procedure TTeUpdateDB.BuiltIDList; var http: TIdHttp; ssl: TIdSSLIOHandlerSocketOpenSSL; buffer: String; begin IDList.Clear; http := TIdHTTP.Create; ssl := TIdSSLIOHandlerSocketOpenSSL.Create(nil); http.IOHandler := ssl; buffer := http.Get('https://url.de/items'); buffer := StringReplace(buffer,'[','',[]); buffer := StringReplace(buffer,']','',[]); IDList.StrictDelimiter := True; IDList.Delimiter := ','; IDList.DelimitedText := buffer; end; procedure TTeUpdateDB.BuiltIDListEx(fstart,fend: Integer); var http: TIdHttp; ssl: TIdSSLIOHandlerSocketOpenSSL; buffer: String; ids: String; i: Integer; sl: TStringList; begin http := TIdHTTP.Create; ssl := TIdSSLIOHandlerSocketOpenSSL.Create(nil); http.IOHandler := ssl; sl := TStringList.Create; try ids := ''; for i := fstart to fend do begin if i <> fend then ids := ids + IDList[i] + ',' else ids := ids + IDList[i]; end; buffer := http.Get('https://url.de/items?ids=' + ids); SplitEntries(sl,buffer); //debugging if sl.Count <> CountEntries(buffer) then state.id := -1; AddToIDListEx(sl,fstart,fend); finally sl.Free; end; end; procedure TTeUpdateDB.AddToIDListEx(sl: TStringList; fstart: Integer; fend: Integer); var i: Integer; d: TTeUpdateDBIDState; pf: Integer; begin for i := 0 to sl.Count -1 do begin d.id := IDList[fstart+i]; pf := Pos('"flags":',sl[i]); if pf = 0 then begin d.AccountBindOnUse := false; d.AccountBound := false; d.HideSuffix := false; d.MonsterOnly := false; d.NoMysticForge := false; d.NoSalvage := false; d.NoSell := false; d.NotUpgradeable := false; d.NoUnderwater := false; d.SoulbindOnAcquire := false; d.SoulBindOnUse := false; d.Unique := false; end else begin d.AccountBindOnUse := (Pos('"AccountBindOnUse"',sl[i],pf) <> 0); d.AccountBound := (Pos('"AccountBound"',sl[i],pf) <> 0); d.HideSuffix := (Pos('"HideSuffix"',sl[i],pf) <> 0); d.MonsterOnly := (Pos('"MonsterOnly"',sl[i],pf) <> 0); d.NoMysticForge := (Pos('"NoMysticForge"',sl[i],pf) <> 0); d.NoSalvage := (Pos('"NoSalvage"',sl[i],pf) <> 0); d.NoSell := (Pos('"NoSell"',sl[i],pf) <> 0); d.NotUpgradeable := (Pos('"NotUpgradeable"',sl[i],pf) <> 0); d.NoUnderwater := (Pos('"NoUnderwater"',sl[i],pf) <> 0); d.SoulbindOnAcquire := (Pos('"SoulbindOnAcquire"',sl[i],pf) <> 0); d.SoulBindOnUse := (Pos('"SoulBindOnUse"',sl[i],pf) <> 0); d.Unique := (Pos('"Unique"',sl[i],pf) <> 0); end; IDListEx.Add(d); end; end; function TTeUpdateDB.CountEntries(s: String): Integer; var p: Integer; begin p := 1; result := 0; while p <> 0 do begin p := Pos('{"name":',s,p+1); if p <> 0 then Inc(result); end; end; procedure TTeUpdateDB.SplitEntries(sl: TStringList; s: String); var p, pp: Integer; b: Boolean; begin sl.Clear; b := true; p := 0; while b do begin p := Pos('{"name":',s,p+1); //1.Item pp := Pos('{"name":',s,p+1); //2.Item if pp = 0 then begin b := false; pp := Length(s); end else begin pp := pp - 1; end; sl.Add(Copy(s,p,pp-p)); end; end; function TTeUpdateDB.BToStr(b: Boolean): String; begin if b then result := '1' else result := '0'; end; end. |
AW: Mein Programm ist Arbeitsspeicher hungrig..
41.000 * 16 Record-Bytes = 656.000 Byte (TList legt das in einem Block in den RAM ... bei 64 KB-Speicherblöcken macht das 10,0098 Blöcke = aufgerundet 11*64 = 720.896 Bytes)
+ 41.000 * (4 Längen-Bytes + 2 CharSize-Bytes + 2 CodepageBytes + 2*2 abschließende #0-Bytes + 5*2 Unicode-Bytes) = 22 ... FastMM wird das vermutlich im 32er-Block ablegen = 1.312.000 Bytes effektiv also 2 MB (in Delphi ab Version 2009) und dazu kommt dann noch die VCL, usw. aber jetzt kommt es noch darauf an, was du eigentlich soonst noch machst, vorallem mit den Strings, wie du die Liste befüllst (mit oder einer passenden Capacity) und wie die deine Speicherverwaltung aussieht, was du für eine Delphiversion benutzt uvm. Wenn das wirklich so viel wird dann liegt das vermutlich an dir und eventuell einer wunderschönen Speicherfragmentierung. Was sagt denn z.B. GetHeapStatus, GetMemoryManagerState, wieviel es wirklich ist? Und wie sieht es mit Speicherlecks aus? (ReportMemoryLeaksOnShutdown) [edit] Deine code hab ich mir jetzt nicht angesehn (ist auch schon spät) |
AW: Mein Programm ist Arbeitsspeicher hungrig..
Das lässt sich viel besser speichern:
EinString : array [0..4] of ANSIChar; // 5 Bytes * 41000 = 205 kB BooleanWerte : uses System.Classes.TBits.Bits var Bits: TBits; I: Byte; begin { Create a a bit set. } Bits := TBits.Create; { Set the size of the bit set. } Bits.Size := 12; // 12 BooleanWerte 61,5 kB ------------------------------------------SUMME : 266,5 kB ![]() |
AW: Mein Programm ist Arbeitsspeicher hungrig..
schaut euch mal bitte meine Code an. Das ist alles. Was ist daran falsch, bzw wieso wird so viel Speicher verbraucht? Die Strings die heruntergeladen werden sind schon relativ groß ~1-2MB allerdings sollten die ja im Grunde keine Rolle spielen, da sie nur lokal sind und dann nicht im speicher bleiben.. Also woran kann das liegen?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz