Entwickler-Ecke

Algorithmen, Optimierung und Assembler - FileStream --> AssignFile


Heiko - Do 22.05.08 20:31
Titel: FileStream --> AssignFile
Hallo,

ich führe momentan mal wieder Performancetests durch. Der vollständigkeit halber möchte ich die alte Lesevariante (das mit file of byte) einbeziehen. Nur da ich damit bisher kaum gearbeitet habe, mal so in die Runde: wie übersetzt man meinen StreamCode am performnatesten in die alte Variante?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
    for j:=0 to TestFileSize-1 do BigBuf[i]:=random(256);
    t:=GetTickCount;
    FS:=TFileStream.Create('Test.txt', fmOpenReadWrite);
    FS.Write(BigBuf[0], TestFileSize);
    FS.Position:=2;
    FS.Read(Buf[1], 2);
    FS.Position:=FS.Size-2;
    FS.Write(Buf[1], 2);
    FS.Size:=10;
    FS.Free;
    inc(t2, GetTickCount-t);


Denn bei der alten Variante habe ich für Zeile 5 z.B. das hier:

Delphi-Quelltext
1:
2:
    Reset(FH);
    Seek(FH, 2);

was sicherlich nicht am schnellsten ist und für Write habe ich bisher nur das Byteweise schreiben gefunden :(.


Delete - Do 22.05.08 22:53
Titel: Re: FileStream --> AssignFile
Du hast den Ressourcn-Schutzblock vergessen, der wird auch noch mal etwas Zeit kostn, aber er gehört dazu.


Heiko - Fr 23.05.08 13:47

Hallo Luckie,

klar würde dies nen bissl Performance kosten. Aber meine Vergleichsunit schmeißt keine Exceptions, die muss man manuell abfragen. Da ich dies im Performancetest bisher nicht abfange, habe ich dies dem entsprechend weggelassen ;). Vlt. baue ich es noch ein. Mal sehen, wie große der Unterschied zwischen try-finally-Blöcken und normalen if-Abfragen ist ;).


Delete - Fr 23.05.08 15:25

Mit if-Abfragen wirst du bei TFileStream nicht weit kommen, weil die Methoden keine Fehlrcodes zurückgeben, sondern Exceptions werfen.


Heiko - Fr 23.05.08 15:27

Bei TFileStream nicht, aber bei TFileStreamW (meiner eigenen Klasse) ;)


BenBE - Mi 28.05.08 10:46

user profile iconLuckie hat folgendes geschrieben:
Mit if-Abfragen wirst du bei TFileStream nicht weit kommen, weil die Methoden keine Fehlrcodes zurückgeben, sondern Exceptions werfen.

Nicht ganz korrekt. TFileStream kapselt einen THandleStream und der nutzt ganz normal die WinAPI, man bekommt also über GetLastError schon eine Meldung zurück. Die Fehlerkondition bekommt man durch Vergleichen von Angeforderter Datenmenge zu gelieferter Datenmenge (wenn man Read und nicht ReadBuffer benutzt).


Motzi - Do 29.05.08 11:59

Wenn aber das File gar nicht erst geöffnet werden kann (weil es nicht existiert, man zuwenig Rechte hat, es gesperrt ist, etc) fliegt aber sehr wohl eine Exception.. :P ;)


Delete - Do 29.05.08 15:36

user profile iconBenBE hat folgendes geschrieben:
user profile iconLuckie hat folgendes geschrieben:
Mit if-Abfragen wirst du bei TFileStream nicht weit kommen, weil die Methoden keine Fehlrcodes zurückgeben, sondern Exceptions werfen.

Nicht ganz korrekt. TFileStream kapselt einen THandleStream und der nutzt ganz normal die WinAPI, man bekommt also über GetLastError schon eine Meldung zurück. Die Fehlerkondition bekommt man durch Vergleichen von Angeforderter Datenmenge zu gelieferter Datenmenge (wenn man Read und nicht ReadBuffer benutzt).

Aber du kannst nicht sicher sein, ob das der letzte Fehler der Dateioperation war. Deswegen würde ich sicherheitshalber die Exceptions behandeln.


BenBE - Do 29.05.08 15:50

Die Exception wird auch erst aus dem Nicht-Übereinstimmen der gelesenen und der angeforderten Anzahl an Bytes generiert. Siehe VCL-Sources ...


Heiko - Di 03.06.08 19:22

@Luckie: BenBE hat schon recht. Die WinAPI wirft imho nur bei einem einzigen BEfehl ne Exeption (zu mindestens steht nur bei einer Funktion das da).

@Überstzung: ich habs inzwischen so hier. Mehr dürfte man nicht rausbekommen.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
    for j:=0 to TestFileSize-1 do BigBuf[i]:=random(256);
    t:=GetTickCount;
    AssignFile(FH, 'Test.txt');
    Reset(FH);
    BlockWrite(FH, BigBuf[1], TestFileSize);
    Seek(FH, 2);
    BlockRead(FH, Buf[1], 2);
    Seek(FH, FileSize(FH)-2);
    BlockWrite(FH, Buf[1], 2);
    Seek(FH, 10);
    Truncate(FH);
    CloseFile(FH);
    inc(t1, GetTickCount-t);