AW: Memory leak durch funktion readln
Tja wer mißt misst Mist:
Datei schreiben: ticks für file1: 998 ticks für file2: 9079 ticks für file1: 5304 ticks für file2: 9313 ticks für file1: 8346 ticks für file2: 10093 Datei lesen: readticks für file1: 515 readticks für file2: 32 readticks für file1: 515 readticks für file2: 15 readticks für file1: 499 readticks für file2: 31 und hier der Source: (der Mißbrauch von written sei mir vergeben):
Delphi-Quellcode:
Wenn ich beim reset/rewrite statt 1 buffersize nutze, gibt es keine signifikante Abweichung.
procedure TForm1.Button1Click(Sender: TObject);
const file1='c:\temp\f1.bin'; file2='c:\temp\f2.bin'; buffersize=8192; maxblocks=$FFFF; var i : integer; fn1, fn2 : tfilestream; dat1, dat2 : file; buffer : array [0..buffersize-1] of byte; sz1,sz2 : integer; ez1,ez2 : integer; written : integer; begin assignfile(dat1,file1); rewrite(dat1,1); fillchar(buffer,buffersize,'A'); sz1:=gettickcount; for i:=0 to maxblocks do blockwrite(dat1,buffer,buffersize); ez1:=gettickcount; closefile(dat1); memo1.Lines.Add(format('ticks für file1: %d',[ez1-sz1])); fn1:=tfilestream.Create(file2,fmcreate or fmshareexclusive ); sz2:=gettickcount; for i:=0 to maxblocks do written:=fn1.Write(buffer,buffersize); ez2:=gettickcount; fn1.Free; memo1.Lines.Add(format('ticks für file2: %d',[ez2-sz2])); end; procedure TForm1.Button2Click(Sender: TObject); const file1='c:\temp\f1.bin'; file2='c:\temp\f2.bin'; buffersize=8192; maxblocks=$FFFF; var i : integer; fn1, fn2 : tfilestream; dat1, dat2 : file; buffer : array [0..buffersize-1] of byte; sz1,sz2 : integer; ez1,ez2 : integer; written : integer; begin assignfile(dat1,file1); reset(dat1,1); fillchar(buffer,buffersize,'A'); sz1:=gettickcount; for i:=0 to maxblocks do blockread(dat1,buffer,buffersize); ez1:=gettickcount; closefile(dat1); memo1.Lines.Add(format('readticks für file1: %d',[ez1-sz1])); fn1:=tfilestream.Create(file2,fmopenread or fmshareexclusive ); sz2:=gettickcount; for i:=0 to maxblocks do written:=fn1.Write(buffer,buffersize); ez2:=gettickcount; fn1.Free; memo1.Lines.Add(format('readticks für file2: %d',[ez2-sz2])); end; Ach ja W7-64 und die Festplatte in meinem Laptop. Die paar hunderstel Unterschied, die Du gemessen hast, würde ich übrigens als Meßfehler abhaken. Gruß K-H |
AW: Memory leak durch funktion readln
OK Neue Testbedingung.
Nativ Windows 8 keine VM. Mächtig große Datei, daher weniger Try's weil es mir sonst zu lange gedauert hätte! Lesen von 29996224 KB - gelesen in Häppchen zu 1048576 KB Versuch 1 : Blockread(45643 ms) StreamRead(45811 ms) 1:0 Versuch 2 : Blockread(45977 ms) StreamRead(45839 ms) 1:1 Versuch 3 : Blockread(45820 ms) StreamRead(45768 ms) 1:2 Versuch 4 : Blockread(45287 ms) StreamRead(45424 ms) 2:2 Versuch 5 : Blockread(45168 ms) StreamRead(45305 ms) 3:2 Best Blockread 648,54 MB/s Best StreamRead 646,58 MB/s Blockread gewinnt... Stopwatch ist da ziemlich genau... Aber bei 45 Sekunden ein Unterschied von 137 ms... Na gut... Meine Rede Blockread & StreamRead sind fast die gleichen Routinen... Bei 4,43 GHz fällt das aber selbst bei so vielen Operationen nicht auf... Mavarik |
AW: Memory leak durch funktion readln
hmm wenn ich Deine Zahlen richtig sehen...
Blockwrite schneller als Streamwrite StreamRead schneller als Blockread... Komisch... Aber Du hast natürlich sehr keine Blockgrößen genommen...
Delphi-Quellcode:
var
Puffer : array [0..1024*1024*1024-1] of byte; implementation Uses System.Diagnostics; procedure TForm42.Button1Click(Sender: TObject); var F : File; FS : TFileStream; SW : TStopWatch; BR,ST : array[0..9] of Int64; I : Integer; Gelesen : Integer; Filename : String; begin Filename := 'Big.iso'; Memo1.Lines.Text := 'Lesen von '+(GetFilesize('Big.iso') / 1024).ToString+' KB - gelesen in Häppchen zu '+(Sizeof(Puffer) / 1024).ToString+' KB'; for i:=0 to 5 do begin AssignFile(F,Filename); Reset(F,1); SW := TStopWatch.StartNew; SW.Start; repeat Blockread(F,Puffer[0],Sizeof(Puffer),gelesen); until gelesen = 0; SW.Stop; Closefile(F); BR[I] := SW.ElapsedMilliseconds; FS := TFileStream.Create(Filename,fmopenRead); SW := TStopWatch.StartNew; SW.Start; repeat gelesen := FS.Read(Puffer[0],Sizeof(Puffer)); until gelesen = 0; SW.Stop; FS.Free; ST[I] := SW.ElapsedMilliseconds; Memo1.Lines.Add('Versuch '+i.ToString+' : Blockread('+BR[i].ToString+' ms) StreamRead('+ST[i].ToString+' ms)'); Application.ProcessMessages; end; end; |
AW: Memory leak durch funktion readln
Der Vorteil von Filestreams liegt ja nicht direkt an der Geschwindigkeit, sondern an der Abstraktion.
Klar ist es schnell mit großen Buffern* zu arbeiten. Aber die meisten Anwendungen lesen logisch häufig kleinere Strukturen. Nun könnte man in der Anwendungslogik irgendeine Bufferverwaltung fest verdrahten; oder man ließt einfach die Größe, die was man gerade braucht, aus einem Stream. Um die Performanz zu verbessern, kann man jetzt eine beliebige Bufferverwaltung, Caches, usw. in einen Stream verpacken und benutzen, ohne den Algorithmus anfassen zu müssen. Und das alles zum Preis von ein paar virtuellen Methodenaufrufen :mrgreen: * Zu große Puffer sind auch nicht das Wahre: Das Betriebssystem schreibt die womöglich flugs wieder in die Auslagerungsdatei, so dass die beim nächsten Zugriff noch mal von der Platte gekratzt werden müssen. |
AW: Memory leak durch funktion readln
Bei den "alten" Datei-Prozeduren hat standardmäßig erstmal nur TEXT einen kleinen 127-Byte Puffer, was sogesehn auch nicht grade optimal ist, da Windows und Hardware Speicher in Größen mit Vielfachen von 512 verwaltet (kleinster Sektor = 512 und das ist heute bei durchschnittlich über 8 KB) und auch der RAM wird in 64-KB-Schritten verwaltet.
Und dann geht/ging man davon auß, daß eine Zeile meistens nicht größer als 127 Byte (ANSI-Zeichen) ist. Zitat:
In binären Formaten gibt es da fast immer feste Größen, bzw. man hat vor den Daten irgendwo eine Größenangabe in Byte/Wort/Integer/... die ja selber wieder eine feste Größe besitzen. |
AW: Memory leak durch funktion readln
Zitat:
|
AW: Memory leak durch funktion readln
Zitat:
Jetzt entspricht das Ergebnis Deinen Zahlen, mit leichen Vorteilen für's Streamread. Sei's drum, halten wir fest, beim lesen tun die beiden sich nich(s/ viel) und beim Schreiben hat Blockwrite die Nase vorn. Gruß K-H |
AW: Memory leak durch funktion readln
Zitat:
Zugegeben die Verwendung von TStream in Grundroutinen macht Sinn, wem man diese dann mit Memory- oder Filestream aufrufen kann... Bei Dateien < Meine_Max_Puffergröße lad ich egal was einfach ins RAM und go... Klar kann ich auch eine Textdatei Zeilenweise einlesen... Aber eine 1MB Textdatei in einem rutsch in den Puffer und dann mit einem
Delphi-Quellcode:
durchlaufen ist echt schneller, wenn ich "nur" etwas Suche!
Zeiger : ^Char
Mavarik |
AW: Memory leak durch funktion readln
Zitat:
dagegen kann man nix machenn oder? |
AW: Memory leak durch funktion readln
Zitat:
|
AW: Memory leak durch funktion readln
Zitat:
Delphi-Quellcode:
Abgesehen von der nicht umwerfenden Geschwindigkeit, gibt es da keine Probleme! Wenn Du Probleme hast, dann ist die Frage wie kommst Du überhaupt darauf?
procedure sterb_schleife;
var quell_dat, grossdatei: text; quelldatname : string; zeile : string; zaehler_gesamt : integer; begin assign(grossdatei, 'c:\temp\'+ 'big.txt'); rewrite(grossdatei); quelldatname := 'test.TXT'; assign(quell_dat, 'c:\temp\' + quelldatname); reset(quell_dat); while not eof(quell_dat){zaehler_gesamt<1200000} do begin readln(quell_dat, zeile); Writeln(grossdatei, zeile); inc(zaehler_gesamt); (* if ((zaehler_gesamt mod 1000) = 0) then dsnr.strings[1] := inttostr(zaehler_gesamt); *) end; flush(quell_dat); close(quell_dat); flush(grossdatei); close(grossdatei); end; Zitat:
Gruß K-H |
AW: Memory leak durch funktion readln
Zitat:
dann "läuft der arbeitsspeicher voll, also das sehe ich daran, dass der grüne balken im ressourcen monitor unter memory der für in use steht immer weiter anwächst. |
AW: Memory leak durch funktion readln
Zitat:
Ist der Speicher wieder frei nach dem Close und ein bisschen Wartezeit? Mavarik |
AW: Memory leak durch funktion readln
Du kannst seine Sterb_schleife 10 mal hintereinander ausführen und der Speicherbedarf ist nach der Ausführung nicht gestiegen. Insofern ist die Bezeichnung "Leak" irreführend.
Es geht nur um den immer weiter steigenden Speicherbedarf innerhalb der Schleife. |
AW: Memory leak durch funktion readln
Zitat:
|
AW: Memory leak durch funktion readln
Zitat:
|
AW: Memory leak durch funktion readln
Zitat:
Oder sagt Reportmemoryleaksonshutdown etwas anderes? |
AW: Memory leak durch funktion readln
Ich glaube eher dass es, egal ob ReadLn, TStreamReader oder sonst was, es nicht am Code, sondern an den Daten liegt. Ich habe bei meiner "steigt immer weiter an"-Aussage vergessen zu erwähnen dass ich das mit einer Testdatei mit einer 300MB langen Zeile versucht habe. Wenn man ein paar Millionen kleine Zeilen untereinander macht ist die sterb_schleife auch vollkommen ok und steigt kein KB im Speicherbedarf.
Oder hast du ein paar Zeilen um eine Testdatei zu erzeugen wie sie bei dir normalerweise aussehen? |
AW: Memory leak durch funktion readln
Zitat:
aber gute idee das mal zu testzwecken mit anderer zeilen länge zu versuchen |
AW: Memory leak durch funktion readln
Zitat:
|
AW: Memory leak durch funktion readln
Zitat:
Gruß K-H |
AW: Memory leak durch funktion readln
Probier mal größer-gleich 128, bzw. größer 255.
Für
Delphi-Quellcode:
siehe System._ReadUString und System._ReadLn,
ReadLn(TEXT, STRING)
sowie für
Delphi-Quellcode:
siehe System._Write0UString und System._WriteLn.
WriteLn(TEXT, STRING)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:31 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