Entwickler-Ecke

Dateizugriff - Datei lesen/schreiben beschleunigen


ak - So 27.07.03 19:28
Titel: Datei lesen/schreiben beschleunigen
Hallo Leute,

ich habe ein Dateitool welches eine Textdatei öffnet und einliesst der Inhalt dieser Datei wird wird anhand von drei Kriterien (die ersten 3 Zeichen der Zeile) in drei verschiedene Dateien aufgeteilt.
Da meine Datei sehr gross ist (über 60 MB) wollte ich mal fragen ob man mit Zeigern mein Dateitool beschleunigen könnte, wenn ja wie ?

hier mal das Programm:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
var
  dateigross, datei101, datei102, datei104: textfile;
  zeile,anfang :string;

begin
  if opendialog1.Execute=True then begin
    assignfile(dateigross,opendialog1.FileName);
    assignfile(datei101,'d101.txt');
    assignfile(datei102,'d102.txt');
    assignfile(datei104,'d104.txt');

    rewrite(datei101);
    rewrite(datei102);
    rewrite(datei104);
    reset(dateigross);

    while not eof(dateigross) do begin
      if not eof(dateigross) then readln(dateigross,zeile);

      anfang := copy(zeile,1,3);
      if anfang = '101' then begin
        append(datei101);
        writeln(datei101,zeile);
      end;
      if anfang = '102' then begin
        append(datei102);
        writeln(datei102,zeile);
      end;
      if anfang = '104' then begin
        append(datei104);
        writeln(datei104,zeile);
      end;


    end;

    closefile(datei101);
    closefile(datei102);
    closefile(datei104);
    closefile(dateigross);
    showmessage('Ihre Datei wurde erfolgreich aufgeteilt.');
  end;

end;


Moderiert von user profile iconTino: Titel geändert.


MSCH - So 27.07.03 19:40

hmmm. wenn ich den Sinn dieser Aktion verstehen würde, könnte ich vielleicht etwas dazu betragen. Aber, was soll es bringen, solche riesigen Dateien nach einem Kürzel der ersten 3 Zeichen zu sortieren ?

Eventuell würde ich das Prob Memory mapped files () angehen? :?
grez
msch


ak - So 27.07.03 19:51

Es handelt sich bei dieser "riesigen" Datei um Daten aus einem Netzwerk. Diese Daten sollen aufgeteilt werden, in drei Dateien. Anhand der ersten 3 Zeichen (101,102,103) kann ich die Daten des Netzwerkes identifizieren und thematisch zuordnen. Das Programm funktioniert ganz gut ist aber bei der Menge an Daten etwas langsam.

Kann man mit Zeigern die Geschwindigkeit verbessern?


MSCH - So 27.07.03 20:16

eher nicht, denn da du sequenziell liest und schreibst, hängt das eher von deiner Platte ab. Die sollte schnell schnell sein (raid ?)
oder:
alles im Speicher machen, Datei einlesen, sortieren sprich trennen und schreiben. (StringLists)
grez
msch


tommie-lie - So 27.07.03 21:02

@MSCH: damit habe ich seinerzeit auch shcon mit Luckie diskutiert: Da er ausschließlich sequenziell liest und schreibt, bringt ein Caching im RAM nichts. Die Daten müssen gelesen und geschrieben werden. So oder so. Die eine if-Abfrage dürfte das ganze um nanosekunden verlangsamen. Genauso sieht es mit einer MMF us, die bringen nur bei vielen, zufälligem Zugriff etwas (sagt übrigens auch MS ;-) ). Der Falschenhals ist hier wirklich die Festplatte.

Aber evtl kann man mit Filestreams das ganze ein wenig (ein wenig!) effizienter machen. Zum einen kann man hier wirklich nur die ersten drei zeichen einlesen, nicht die ganze Zeile, und danach kann man in der Clustergröße der Festplatte lesen (ich weiß grad' nicht, ob Append das autoamtisch micht, eher nicht). Dadurch entsteht weniger Leseoverhead. Aber heutige Windows-Versionen mit ihrem "Read Ahead"-Mechanismus kompensieren das auch wieder, sodaß sich das vemrutlich nciht wesentlich beschleunigen lässt. Das wäre aber die einzige wirklich sinnvolle Möglichkeit.


scrooge - Mo 11.08.03 16:17

Hi,

hab mal ein Programm geschrieben, was auch mit ner ziemlich großen Datei zu tun hatte (100+ MB). Hab das ganze mit TFilestream, und TWriter gemacht, denn soweit ich weiß schreibt der die daten dann nicht nur in den SPeicher, sondern auch direkt in die Datei. Du müsstest also puffern (geht ganz gut mit TWriter). MIt TWriter must du nämlcih erst FlushBuffer aufrufen, damit der da schreibt.So ruft der FlushBuffer praktisch bei jedem Write-Aufruf aus, was ziemlich pPerformance kostet.
Zum Performancegewinn: Brauchte vorher 20 Sek danach nur noch 5 !!
:D


AndyB - Mo 11.08.03 17:44

Die obige Methode mit ReadLn puffert auch. Jede TextFile Variable hat einen vorgegebenen Puffer, der automatisch erzeugt wird und das war schon zu DOS Zeiten so. Der Vorgabewert ist 128 Bytes. Vergrößern kann man ihn so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  Buf: array[0..4096 - 1] of Byte; // Memory Page = 4 KB
  f: TextFile;
begin
  AssignFile(f, 'xyz');
  SetTextBuf(f, Buf, SizeOf(Buf)); // <-- eigenen Puffer einsetzen

  Rewrite(f); // Reset(f);
 // ...
  CloseFile(f);  
end;


recall - Mi 13.08.03 18:38

Hallo,

Ist vielleicht eine blöde Idee, aber so in Richtung MS-RamDrive ?
Also virtuelle Festplatte im RAM ???
Bei 60 MB ja kein Problem :)

Danach die Datei einfach kopieren

Könnte das funktionieren ?

Viele Grüsse.


AndyB - Mi 13.08.03 19:04

Das läuft auf gleiche hinaus als wenn man in einen MemoryStream schreibt und diesen danach in einem Zug in einen TFileStream schreibt. Wobei die RAMDrive Methode einiges mehr an Verwaltungsaufwand benötigt.


recall - Mi 13.08.03 22:09

Vielleicht ists ja auch noch langsamer, aber ich meinte eigentlich:
Die Quelldatei ins RAM kopieren, dann auslesen :) .

Viele Grüsse.


AndyB - Mi 13.08.03 22:47

recall hat folgendes geschrieben:
Die Quelldatei ins RAM kopieren, dann auslesen

So habe ich das auch verstanden. Aber wo liegt in folgenden beiden Sätzen der Unterschied?

Mit TMemoryStream: Die Datei in den RAM laden.
Mit RAMDrive: Die Datei in den RAM laden.

Wobei RAMDrive noch ein klein wenig langsamer ist, da es ein Dateisystem zu verwalten gibt.


recall - Do 14.08.03 13:55

gibt keinen, habe dich nur falsche verstanden...

Nur aus Interesse:
@ak: Sag mal, wie lange braucht das Auslesen denn eigentlich ?

Viele Grüsse.