Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Geschwindigkeitsunterschied TFilestream TMemorystream (https://www.delphipraxis.net/56859-geschwindigkeitsunterschied-tfilestream-tmemorystream.html)

etom291272 12. Nov 2005 12:51


Geschwindigkeitsunterschied TFilestream TMemorystream
 
Tag zusammen

folgender Code lest alle Dateien die sich in der übergebenen Stringlist befinden in einen Stream
der noch anschliessend komprimiert wird.
Delphi-Quellcode:
procedure TClDateiTransfer.ErzStreamObjUbertr(aObjList: TStringList; StatusBar:TStatusBar);
var
  aFs:TFileStream;
  aTempFs:TFileStream oder TMemorystream;
  aDateiGr:Int64;
  aDatName:String;
  i:Integer;
begin
  aTempFs:=TFileStream.Create('temp.str',fmCreate); //TMemoryStream.Create;
  try
    for i:=0 to aObjList.Count-1 do
    begin
      aFs:=TFileStream.Create(aObjList.Strings[i], fmOpenRead);
      try
        aDateiGr:=aFs.Size;
        aTempFs.Write(aDateiGr, sizeof(aDateiGr));

        aDatName:=ExtractFileName(aObjList.Strings[i]);
        StringStrSpeichn(aDatName, aTempFs);

        StatusBar.Panels[0].Text:='... bearbeite '+aDatName;
        Application.ProcessMessages;
        sleep(100);

        aTempFs.CopyFrom(aFs, aFs.Size);
      finally
        aFs.Free;
      end;
    end;
    StatusBar.Panels[0].Text:='... Dateien werden komprimiert';
    Application.ProcessMessages;

    aTempFs.Position:=0;
    ZCompressStream(aTempFs, poStreamUbertr, zcFastest);

    StatusBar.Panels[0].Text:='... starte Übertragung';
    Application.ProcessMessages;
  finally
    aTempFs.Free;
    DeleteFile('temp.str');
  end;
end;
Ich wollte eigentlich das ganze ohne zwischendateien lösen das funktionierte auch wunderbar mit memorystream mit kleinen dateien. Dann testete ich das verfahren allerdings mit grossen files
3 dateien (2 mit 38 Mb und 1 mit 26 Mb) also zusammen ca 100 Mb und stellte etwas sehr merkwürdiges fest:

der Stream der zu komprimieren ist wird in der variable aTempFs gespeichert entweder Klasse TFilestream oder TMemorystream

Mit TMemoryStream brauchte der code bis vor der komprimierung über 3 Min :wall: :wall:
Mit TFilestream ca 15 sec :thumb:

Kann mir das bitte jemand erklären warum normal müsste doch Ram schneller als Platte sein :?:
Gibts es eine andere Möglichkeit um MemoryStream schneller zu machen :?:

Luckie 12. Nov 2005 12:55

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
Nicht wenn der Adressraum deiner Anwendung stark fragemnetiert ist, denn dann bekommt der Memorymanager ziemliche Problem Speicherblöcke zur Verfügung zu stellen, die groß genug sind. Jedenfalls würde ich mir das so erklären.

etom291272 12. Nov 2005 12:57

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
das heist in meinem fall sollte ich mit filestream arbeiten und die temp datei nachher löschen :?:

ichbins 12. Nov 2005 12:59

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
was ist so schlimm daran? du kannst ja überprüfen ob du genügend platz für die temp hast und wenn ja den filestream nehmen und wenn nein den memorystream.

etom291272 12. Nov 2005 13:04

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
es ist nichts schlimm dran mich hat es nur interessiert ob man den code für den memorystream ändern und damit schneller machen kann oder ob für solche aufgaben generell ein filestream zu empfehlen ist.

Union 12. Nov 2005 13:12

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
Wenn Du folgenden Code vor der For-Schleife einfügst, dauert auch nur 3 Sekunden, weil der Speicher in einem Mal am Stück reserviert wird (evtl. musst Du noch etwas für die Dateinamen hinzufügen, weil ich nicht weiss, was Du in StringStrSpeichn tust):
Delphi-Quellcode:
    aDateiGr := 0;
    for i:=0 to aObjList.Count-1 do
    begin
      aFs:=TFileStream.Create(aObjList.Strings[i], fmOpenRead);
      try
        aDateiGr:= aDateiGr+aFs.Size+length(aObjList.Strings[i])+1;
      finally
        aFs.Free;
      end;
    end;
    // Speicher wird nur einmal reserviert
    aTempFs.SetSize(aDateiGr);
    // Hier geht's mit Deinem Code weiter
    for i:=0 to aObjList.Count-1 do

etom291272 12. Nov 2005 13:28

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
hallo union

hier erstmal die funktion StringStrSpeichn
Delphi-Quellcode:
procedure TClDateiTransfer.StringStrSpeichn(ZeichenFolge: String;
  ZielStr: TStream);
var i: Integer;
begin
  i := Length(ZeichenFolge);
  ZielStr.Write(i, sizeof(i));
  ZielStr.Write(ZeichenFolge[1], i);
end;
in der Stringlist stehen 1-x Vollständige Dateinamen (kompletter Pfad + Dateiname + ext)
in den stream wird dann je item in der stringlist folgendes geschrieben:
Dateigrösse / Dateiname+ext (Bsp. KU_Mapos.Dat) / die eigentliche Datei

dein vorschlag hört sich sehr gut an.
was gehört hier hin
Delphi-Quellcode:
try
   aDateiGr:= aDateiGr+aFs.Size+length(aObjList.Strings[i])+1; //warum +1 ???
   //imho aDateiGr:=sizeof(aDateiGr)+???+aFs.Size
   //Speicher für Int64 + Speicher für String (Dateiname+ext)+ Speicher für Datei binär
finally
   aFs.Free;
end;
oder :?:

etom291272 12. Nov 2005 14:12

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
Danke union war wiedermal hammertip

Delphi-Quellcode:
   aDateiGr := 0;
    for i:=0 to aObjList.Count-1 do
    begin
      aFs:=TFileStream.Create(aObjList.Strings[i], fmOpenRead);
      try
        aDatName:=ExtractFileName(aObjList.Strings[i]);
        //aDateiGr:= aDateiGr+aFs.Size+length(aObjList.Strings[i])+1;
        aDateiGr:=aDateiGr + sizeof(aDateiGr)+sizeof(i)+sizeof(aDatName)+aFs.Size;
      finally
        aFs.Free;
      end;
    end;

    aTempFs.SetSize(aDateiGr);
    StatusBar.Panels[0].Text:='... reserviert '+IntToStr(aDateiGr);
:hello: :hello: :hello:
die selben 3 dateien brauchen jetzt mit dem Memorystream unter 4 sekunden bis die komprimierung startet

Union 12. Nov 2005 15:01

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
Delphi-Quellcode:
 aDateiGr:=aDateiGr + sizeof(aDateiGr)+sizeof(i)+sizeof(aDatName)+aFs.Size;
Du darfst dort nicht mit SizeOf(aDatName) arbeiten, das gibt nämlich ein Byte mehr zurück.
Delphi-Quellcode:
 Showmessage(Format('Length(''ABC'') => %d'#13'SizeOf(''ABC'') => %d', [Length('ABC'), Sizeof('ABC')]));
Zitat:

Zitat von Project1
Length('ABC') => 3
SizeOf('ABC') => 4
---------------------------
OK
---------------------------


DGS 25. Mär 2006 19:29

Re: Geschwindigkeitsunterschied TFilestream TMemorystream
 
Also SizeOf(String) liefert IMMER 4 zurück!
Das Liegt dadran, dass im String nur eine Zeiger auf den Speicher gespeichert wird. Dieser zeiger ist dabei halt 4 bytes gross.
Also bei Strings NIE SizeOf nutzen.

Immer Lenght benutzen.
Denn ein SizeOf(string)-1 würde dementsprechend immer 3 zurückliefern, egal wielang der String ist.

( Späte Antwort... war auf der Suche nach etwas, was komprimieren kann... und dabei ned aufs Datum geschaut )


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz