Einzelnen Beitrag anzeigen

Benutzerbild von WordsBG
WordsBG

Registriert seit: 17. Sep 2005
63 Beiträge
 
Delphi 7 Professional
 
#1

TStrings ist *unglaublich* langsam

  Alt 18. Jul 2007, 01:10
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: Klick. Nun gibt es für das (noch) neuste GTA "San Andreas" im Grunde nur zwei Editoren zum dekompilieren/neu kompilieren dieser Datei, von denen einer nicht mehr gewartet wird und unter massiven Fehlern leidet und ein zweiter (aus Russland), welcher "nur" Freeware ist und dem (meiner Meinung nach) noch einige Features fehlen um perfekt zu sein. Jedenfalls habe ich mir überlegt meine Delphi Erfahrung (müssten nun 3 Jahre sein) zu nutzen um einen weiteren Open-Source Editor zu basteln. Bisher allerdings hatte ich noch keine größere Erfahrung mit binären Dateien, doch TFileStream machte im gepufferten Zustand kaum Probleme, ganz im Gegensatz zu meinem alten Freund TStrings der scheinbar mit meiner massiven Anzahl an Updates kaum klarkommt.
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:
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) = 'A4then
        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;
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.
Angehängte Dateien
Dateityp: zip gta_sa_-_mission_coder_115.zip (28,7 KB, 5x aufgerufen)
  Mit Zitat antworten Zitat