AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Memory leak durch funktion readln

Ein Thema von danieldelphi · begonnen am 12. Mär 2015 · letzter Beitrag vom 13. Mär 2015
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.368 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 12:31
Naja, wenn ich es richtig sehe, bekommt "autodatei" kein Close.
Das mag Windows überhaupt nicht, weil dadurch File-Handles nicht wieder freigegeben werden. Das kann in der Folge dann auch zu Memory-Leaks führen.

Mal abgesehen davon, dass in der inneren While-Schleife ein Exit steht. Wodurch keine einzige Datei-Variable mehr freigegeben wird.

Oder habe ich das Close für autodatei übersehen?
Peter
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#2

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 12:47
Richtig, das sind zwei weitere Probleme. Aber, der TE hat doch mit FastMM geprüft. Müsste der dann nicht anschlagen?
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.368 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 12:51
Weiß ich nicht sicher, da ich mich mit FastMM nicht besonders gut auskenne.
Allerdings ist das mit den File-Handles in dieser Konstellation meines Wissens ein Windows-Problem. Das könnte evtl. an FastMM vorbei gehen.

EDIT:
Dann hab ich weiter gesucht und iwo gelesen, dass FastMM keine leaks bezüglich externer Datein findet, ...
Peter

Geändert von Jasocul (12. Mär 2015 um 12:59 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 15:47
Naja, wenn ich es richtig sehe, bekommt "autodatei" kein Close.
Das mag Windows überhaupt nicht, weil dadurch File-Handles nicht wieder freigegeben werden. Das kann in der Folge dann auch zu Memory-Leaks führen.
Sag ich doch, Chaos!
Das letzte mal, als ich so wilde Dateioperationen durchgeführt habe, war noch kein Delphi existent.

[OT]
@Mavarik glaub ich Dir gerne, aber da die Blockwrite/Blockread-s definitv langsamer waren als das Filestream.Read/write, hab ich alles umgestellt (seit D7/XP) u.U. gibt es da ja noch ein paar Nebensächlichkeiten, die sich auswirken!?)
[/OT]

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von FaTaLGuiLLoTiNe
FaTaLGuiLLoTiNe

Registriert seit: 3. Jul 2004
Ort: NRW
55 Beiträge
 
Delphi XE Enterprise
 
#5

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 16:28
Eine wesentliche Verbesserung des gezeigten Quelltextes würde - wohl auch im Hinblick auf das Thema dieses Threads - in der Verwendung von Ressourcenschutzblöcken bestehen...
Christian
<< FaTaLGuiLLoTiNe >>
Rhinoceroses don't play games!
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.154 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 22:14
[OT]
@Mavarik glaub ich Dir gerne, aber da die Blockwrite/Blockread-s definitv langsamer waren als das Filestream.Read/write, hab ich alles umgestellt (seit D7/XP) u.U. gibt es da ja noch ein paar Nebensächlichkeiten, die sich auswirken!?)
[/OT]
hmm... Wüste nicht was, aber nix was man nicht mal testen kann... (Dir zu liebe)

Lesen von 5.291.584 KB - gelesen in Häppchen zu 1.048.576 KB

Versuch 0 : ohne Wertung wegen Windows Cache lesen.

Versuch 1 : Blockread(1405 ms) StreamRead(1408 ms) 1:0
Versuch 2 : Blockread(1414 ms) StreamRead(1404 ms) 1:1
Versuch 3 : Blockread(1411 ms) StreamRead(1408 ms) 1:2
Versuch 4 : Blockread(1416 ms) StreamRead(1407 ms) 1:3
Versuch 5 : Blockread(1406 ms) StreamRead(1409 ms) 2:3
Versuch 6 : Blockread(1421 ms) StreamRead(1423 ms) 3:3
Versuch 7 : Blockread(1423 ms) StreamRead(1417 ms) 3:4
Versuch 8 : Blockread(1407 ms) StreamRead(1411 ms) 4:4
Versuch 9 : Blockread(1408 ms) StreamRead(1410 ms) 5:4

Ätsch Blockread hat mit 5:4 gewonnen...

Gemessen in einer Windows 7/64 VMWare

Geändert von Mavarik (12. Mär 2015 um 22:53 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#7

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 23:22
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:
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;
Wenn ich beim reset/rewrite statt 1 buffersize nutze, gibt es keine signifikante Abweichung.

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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector

Geändert von p80286 (12. Mär 2015 um 23:28 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.154 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 23:49
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
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.154 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Memory leak durch funktion readln

  Alt 12. Mär 2015, 23:57
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;
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#10

AW: Memory leak durch funktion readln

  Alt 13. Mär 2015, 01:22
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

* 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.

Geändert von BUG (13. Mär 2015 um 01:24 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:24 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