![]() |
TStrings ist *unglaublich* langsam
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo!
Ich habe ein Problem bei einem Programm an dem ich gerade arbeite. Sicher habt ihr schon einmal von GTA (Grand Theft Auto) gehört und wenn ihr dort Erfahrung habt wisst ihr vielleicht, dass es rund um diese Spieleserie eine große internationale Fangemeinde gibt, die sich im speziellen mit dem Modden des Spiels beschäftigt. Da mich neue Autos und ähnliches weniger interessieren, bin ich meistens bei den Scriptern unterwegs. Die GTA-Engine nutzt eine binär-kompilierte Datei (main.scm). Diese hat einen recht simplen Aufbau, welcher sich hier nachlesen lässt: ![]() Die Standard main.scm ist ca. 3mb groß, getestet habe ich alles an einer 1kb main.scm und alles lief prima, doch schon bei rund 70kb macht mir TString massive Probleme. Wenn ich alle Ausgabe-Befehle auskommentiere läuft es innerhalb von zwei Sekunden durch, genau wie es sollte, mit TStrings wird es mit steigender kb Zahl immer langsamer (ersichtlich wenn man sich die abgearbeiteten kb ausgeben lässt), so dauert es von 2 auf 3 kb einige Sekunden und von 61 auf 62 ewige Jahre. Deshalb, nach dieser ewigen Einleitung, meine Frage was ich dagegen tun könnte. Hier der Quellcode der entsprechenden Funktion (muss evt. noch an einigen Stellen geändert werden ;)).
Delphi-Quellcode:
Angehängt mal das komplette Projekt, falls jemand eine Idee hat (beide scms [70kb + mini 1kb] sind mal mit drin, zum testen [Beide übrigens inoffiziell und somit nicht vom Copyright des Spieleherstellers betroffen]). Oh und ja, mein Programm entziffert den Header (noch) nicht.
procedure TfrmMain.btnOpenClick(Sender: TObject);
var FS: TJclBufferedStream; I, J, K: Integer; Ch : Char; EndOfHeader: Boolean; High, Low: String; IsHigh: Boolean; Param: Integer; ParamTyp, ParamSCMStr: String; ini: TINIFile; begin if NOT OpenDialog.Execute then Exit; Code.Lines.Clear; EndOfHeader := False; IsHigh := False; try Code.Lines.BeginUpdate; FS := TJclBufferedStream.Create(TFileStream.Create(OpenDialog.FileName, fmOpenRead),True); ini := TINIFile.Create(ExtractFilePath(Application.ExeName)+'SASCM.ini'); I := 0; While I < FS.Size do begin Caption := FloatToStr(I DIV 1024); Application.ProcessMessages; FS.Read(Ch, SizeOf(Ch)); if IntToHex(Ord(Ch),2) = 'A4' then EndOfHeader := True; if NOT EndOfHeader then Code.Lines.Text := Code.Lines.Text + IntToHex(Ord(Ch),2) else begin If IsHigh then High := IntToHex(Ord(Ch),2) else Low := IntToHex(Ord(Ch),2); if isHigh then begin ParamSCMStr := ini.ReadString('main',LowerCase(High+Low),'0,'); ParamSCMStr := Copy(ParamSCMStr, Pos(',',ParamSCMStr)+1, Length(ParamSCMStr)); Code.Lines.Add(GetOP(High, Low, ParamSCMStr)); ParamSCMStr := ini.ReadString('main',LowerCase(High+Low),'0,'); ParamSCMStr := Copy(ParamSCMStr,1,Pos(',',ParamSCMStr)-1); for K := 1 to StrToInt(ParamSCMStr) do begin Application.ProcessMessages; FS.Read(Ch, SizeOf(Ch)); I := I + 1; Param := Ord(Ch); case Param of 01: begin Param := 4; ParamTyp := 'INT32'; end; 02: begin Param := 2; ParamTyp := 'GVAR'; end; 03: begin Param := 2; ParamTyp := 'LVAR'; end; 04: begin Param := 1; ParamTyp := 'INT8'; end; 05: begin Param := 2; ParamTyp := 'INT16'; end; 06: begin Param := 4; ParamTyp := 'FLOAT32'; end; 07: begin Param := 6; ParamTyp := 'GARRAY'; end; 08: begin Param := 6; ParamTyp := 'LARRAY'; end; 09: begin Param := 8; ParamTyp := 'STR8'; end; 10: begin Param := 2; ParamTyp := 'GSTR8'; end; 11: begin Param := 2; ParamTyp := 'LSTR8'; end; 12: begin Param := 6; ParamTyp := 'GSTRA8'; end; 13: begin Param := 6; ParamTyp := 'LSTRA8'; end; 14: begin FS.Read(Ch, SizeOf(Ch)); I := I + 1; Param := Ord(Ch); ParamTyp := 'USTR'; end; 15: begin Param := 16; ParamTyp := 'STR16'; end; 16: begin Param := 2; ParamTyp := 'GVSTR'; end; 17: begin Param := 2; ParamTyp := 'LVSTR'; end; 18: begin Param := 6; ParamTyp := 'GVSTRA'; end; 19: begin Param := 6; ParamTyp := 'LVSTRA'; end; else begin Param := 0; ParamTyp := ''; end; end; if ParamTyp <> '' then begin Code.Lines.Text := Code.Lines.Text + ParamTyp + ' '; for j := Param downto 1 do begin FS.Read(Ch, SizeOf(Ch)); I := I + 1; Code.Lines.Text := Code.Lines.Text + IntToHex(Ord(Ch),2)+' '; end; end; end; end; IsHigh := NOT IsHigh; end; I := I + 1; end; finally FS.Free; ini.Free; Code.Lines.EndUpdate; end; end; |
Re: TStrings ist *unglaublich* langsam
Das ist eine Bremse:
Delphi-Quellcode:
Jedes mal, wenn auf die Texteigenschaft zugegriffen wird, wird alles ausgelesen. Warum nimmst du nicht die Methode Add von Lines?
Code.Lines.Text := Code.Lines.Text + ParamTyp + ' ';
|
Re: TStrings ist *unglaublich* langsam
Zitat:
edit: Ok, vielen Dank. Dein Tipp hat hier wirklich geholfen und den Prozess um das 1000-fache beschleunigt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:35 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-2025 by Thomas Breitkreuz