Discussion:
TFileStream und der Dateizugriff blockiert
(zu alt für eine Antwort)
Christian Schmitt
2017-01-28 08:32:00 UTC
Permalink
Hallo Leute,

darf ich mal wieder eure Expertise anfragen? Ich habe eine Anwendung, die auf Messages von extern reagiert. Jede Message wird dabei in eine Logdatei geschrieben mittels einem TFileStream. Es kommen ca. 20. Messages pro Sekunde an und hier und da kommt es dabei leider zu Exception, dass die Logdatei gerade von einem anderen Programm in Benutzung sei. Dem ist aber nicht so, es ist definitiv nur meine Anwendung die die Logdatei schreibt. Ich dachte zuerst, vielleicht gibt es eine "parallele" Ausführung der Prozedur, so dass der erste Filestream noch nicht geschlossen ist, also habe ich das ganze mit einem selbstgebauten FileIsOpen Flag und einem "while FileIsOpen do" gesperrt. Dies half leider nichts. Ich dachte dann vielleicht an den Windows Cache, dass es hier vielleicht zu Problemen kommt, habe somit also ein FlushFileBuffers ausprobiert. Leider ist das Problem immer noch nicht verschwunden. Kann mir jemand sagen, was hier passiert? Es ist auch nur ein Thread im Spiel...

Sind 20 Messages pro Sekunde im übrigen zu viel, wenn ich sie speichern möchte (fixe SSD ist eingebaut ;-) )? Kann ich irgendwie feststellen, ob die Message-Queue voll läuft, wenn das Speichern z.b. zu lange dauert? Was passiert wenn diese voll läuft? Gibt es dann eine Exception oder werden nur keine weiteren Messages angenommen?

Danke nochmal!

Gruß
Jens Köhler
2017-01-28 08:47:52 UTC
Permalink
Post by Christian Schmitt
Hallo Leute,
darf ich mal wieder eure Expertise anfragen? Ich habe eine Anwendung,
die auf Messages von extern reagiert. Jede Message wird dabei in eine
Logdatei geschrieben mittels einem TFileStream.
Danke nochmal!
Gruß
Hallo,

öffnest und schließt Du den Filestream für jede Message neu?

Wie ist es, wenn Du den Stream einmal öffnest, die Message schreibst und
am Programmende schließt?

Jens
Christian Schmitt
2017-01-28 19:51:27 UTC
Permalink
Post by Jens Köhler
öffnest und schließt Du den Filestream für jede Message neu?
Ja genau...
Post by Jens Köhler
Wie ist es, wenn Du den Stream einmal öffnest, die Message schreibst und
am Programmende schließt?
sehr gute Idee, hätte ich auch glatt selbst drauf kommen können :-) Werde ich versuchen!

Gruß
Christian Schmitt
2017-02-01 05:56:50 UTC
Permalink
Also, funktioniert wunderprächtig, nur ist es so, dass nach ca. 45 Minuten wohl meine Message-Queue Vollgelaufen ist, das Programm reagiert dann fur ca. 1 Minute nicht mehr auf eingaben und die Logdatei fällt in der Zeit schmäler aus (weniger Einträge). Jetzt habe ich gelesen, dass TFileStream relativ langsam wäre, ist das immer noch so? Was würdet Ihr mir für ein schnelles Schreiben auf die Festplatte empfehlen? Eher AssignFile?

Gruß
Hans-Peter Diettrich
2017-02-01 08:40:30 UTC
Permalink
Post by Christian Schmitt
Also, funktioniert wunderprächtig, nur ist es so, dass nach ca. 45
Minuten wohl meine Message-Queue Vollgelaufen ist, das Programm
reagiert dann fur ca. 1 Minute nicht mehr auf eingaben und die
Logdatei fällt in der Zeit schmäler aus (weniger Einträge).
Bei 20 Msg/s sieht mir das nach einem grundsätzlichen Fehler im Programm
aus.
Post by Christian Schmitt
Jetzt
habe ich gelesen, dass TFileStream relativ langsam wäre, ist das
immer noch so?
Kann eigentlich nicht sein, der drunterliegende THandleStream greift
direkt auf den Windows Stream zu. Da wird noch so viel vom System
gepuffert, daß es ziemlich egal ist, wie genau die Daten in den Stream
geschrieben werden.
Post by Christian Schmitt
Was würdet Ihr mir für ein schnelles Schreiben auf die
Festplatte empfehlen? Eher AssignFile?
AssignFile ist ziemlich sicher keine Lösung.

Eine Zeit lang gab es einen Hype um MMF (Memory Mapped Files), dürfte
aber real (und beim Schreiben) auch keine grundsätzliche Verbesserung
bringen.

Was ich mir noch vorstellen könnte wäre asynchrone I/O, dann wartet Dein
Programm nicht, bis jede Ausgabe abgeschlossen ist. Siehe WriteFile und
WriteFileEx API.

DoDi
Christian Schmitt
2017-02-02 12:35:49 UTC
Permalink
Post by Hans-Peter Diettrich
Bei 20 Msg/s sieht mir das nach einem grundsätzlichen Fehler im Programm
aus.
Habe mal ausgewertet, es sind tatsächlich so ca. 360 Msg pro Min. Sobald ich das Speichern der Logdatei überspringe, läuft alles glatt. Ich habe nur eben gesehen, dass ich noch das FlushFileBuffers drin hatte, vielleicht bremst das aus.
Post by Hans-Peter Diettrich
Kann eigentlich nicht sein, der drunterliegende THandleStream greift
direkt auf den Windows Stream zu. Da wird noch so viel vom System
gepuffert, daß es ziemlich egal ist, wie genau die Daten in den Stream
geschrieben werden.
Ich bin nur über

http://www.pjh2.de/delphi/articles/files/files.php

gestolpert, das sah für mich nach langsam aus :-)
Post by Hans-Peter Diettrich
AssignFile ist ziemlich sicher keine Lösung.
Eine Zeit lang gab es einen Hype um MMF (Memory Mapped Files), dürfte
aber real (und beim Schreiben) auch keine grundsätzliche Verbesserung
bringen.
Was ich mir noch vorstellen könnte wäre asynchrone I/O, dann wartet Dein
Programm nicht, bis jede Ausgabe abgeschlossen ist. Siehe WriteFile und
WriteFileEx API.
Okay, ich schaue es mir mal an, sollte ein Entfernen des FlushFileBuffer-Befehls nichts bringen... Danke!

Gruß
Hans-Peter Diettrich
2017-02-02 19:14:23 UTC
Permalink
Am Mittwoch, 1. Februar 2017 09:40:43 UTC+1 schrieb Hans-Peter
Post by Hans-Peter Diettrich
Bei 20 Msg/s sieht mir das nach einem grundsätzlichen Fehler im
Programm aus.
Habe mal ausgewertet, es sind tatsächlich so ca. 360 Msg pro Min.
Sobald ich das Speichern der Logdatei überspringe, läuft alles glatt.
Ich habe nur eben gesehen, dass ich noch das FlushFileBuffers drin
hatte, vielleicht bremst das aus.
Ziemlich sicher :-(
Post by Hans-Peter Diettrich
Kann eigentlich nicht sein, der drunterliegende THandleStream
greift direkt auf den Windows Stream zu. Da wird noch so viel vom
System gepuffert, daß es ziemlich egal ist, wie genau die Daten in
den Stream geschrieben werden.
Ich bin nur über
http://www.pjh2.de/delphi/articles/files/files.php
gestolpert, das sah für mich nach langsam aus :-)
Ich traue keinem Benchmark, den ich nicht selbst getürkt habe.
Zeichenweises Lesen ist so ziemlich das übelste, was man zum Vergleich
heranziehen kann :-(

Von D3 auf D4 hat sich viel geändert, und auch Windows ist auf mehr
Durchsatz getrimmt worden.

DoDi

Jens Köhler
2017-02-01 13:16:39 UTC
Permalink
Post by Christian Schmitt
Also, funktioniert wunderprächtig, nur ist es so, dass nach ca. 45
Minuten wohl meine Message-Queue Vollgelaufen ist, das Programm
reagiert dann fur ca. 1 Minute nicht mehr
Gruß
Was schreibst Du für Datenberge in die Datei?
Was macht das Programm nebenbei noch, hat es überhaupt Zeit zum schreiben?

Jens
Christian Schmitt
2017-02-02 12:40:01 UTC
Permalink
Post by Jens Köhler
Was schreibst Du für Datenberge in die Datei?
Was macht das Programm nebenbei noch, hat es überhaupt Zeit zum schreiben?
Eigentlich gar nicht so viel, pro Message ca. 50 Zeichen (Stringkette). Nebenbei laufen noch ein paar Threads die via HTTP kommunizieren, aber nichts weldbewegendes (Nein, es ist auch kein Deadlock, schon überprüft ;-) ). Und alle 3 Sekunden werden noch 10 Charts mit einem Messwert gefüllt, der aber auch wiederum in eine Datei geschrieben wird. Nur das denke ich kann ja fast nicht die Handbremse sein, 3 Sekunden ist ja ne Ewigkeit :-) Wie gesagt, ohne das Schreiben der og. Zeichen läuft das Programm wunderbar rund...
Jens Köhler
2017-02-02 14:41:26 UTC
Permalink
Post by Christian Schmitt
Post by Jens Köhler
Was schreibst Du für Datenberge in die Datei?
Was macht das Programm nebenbei noch, hat es überhaupt Zeit zum schreiben?
Eigentlich gar nicht so viel,
Schreib doch mal ein kleines Testprogamm, das nur in einer Schleife 1000
oder 10.000 mal oder öfter Deinen String in eine Datei schreibt.
Wenn Dein String irgendwie zusammengebaut wird, auch mit dieser Funktion.
Miss die Zeit die das braucht. Daraus kannst Du bestimmen, wie lange ein
Schreibvorgang braucht.

Jens
Jens Köhler
2017-02-02 15:31:27 UTC
Permalink
Post by Jens Köhler
Post by Christian Schmitt
Post by Jens Köhler
Was schreibst Du für Datenberge in die Datei?
Was macht das Programm nebenbei noch, hat es überhaupt Zeit zum schreiben?
Eigentlich gar nicht so viel,
Schreib doch mal ein kleines Testprogamm,
Jens
Gerade mal schnell selbst getestet.
Das normale schreiben einer Zeil dauert im Mikrosekundenbereich.
Das einfügen von FlushFileBuffers pro Schreiben verlängert die Zeit auf
65 Millisekunden pro Schreibvorgang!!!

procedure TForm1.Button1Click(Sender: TObject);
var
z, Anz : integer;
Stream : TFileStream;
FileName : string;
s : string;
T1, t2 : cardinal;
begin
Anz := 10000;
FileName := 'test.txt';

if not FileExists(FileName) then
Stream := TFileStream.Create(FileName, fmCreate)
else
Stream := TFileStream.Create(FileName, fmOpenReadWrite or
fmShareDenyNone);
try
T1 := GetTickCount;
for z := 0 to Anz do
begin
s := 'Das ist nur ein Versuchstext ' + DateTimeToStr(now)+#13#10;
Stream.Write(s[1], Length(s));
// FlushFileBuffers(Stream.Handle);
end;
T2 := GetTickCount - T1;
finally
Stream.Free;
end;
Label1.Caption := 'Zeit ' + IntToStr(T2) + 'ms ' +
FloatToStr(T2 / Anz) + ' pro Schreiben.';

end;
Peter Below
2017-01-28 09:14:09 UTC
Permalink
Post by Christian Schmitt
Hallo Leute,
darf ich mal wieder eure Expertise anfragen? Ich habe eine Anwendung,
die auf Messages von extern reagiert. Jede Message wird dabei in eine
Logdatei geschrieben mittels einem TFileStream. Es kommen ca. 20.
Messages pro Sekunde an und hier und da kommt es dabei leider zu
Exception, dass die Logdatei gerade von einem anderen Programm in
Benutzung sei. Dem ist aber nicht so, es ist definitiv nur meine
Anwendung die die Logdatei schreibt.
Das glaubst Du, aber der Glaube hat schon viele in die Irre geführt ;-).

Da gibt es Virenscanner, die jede neue Datei sofort scannen müssen, da
sonst die Welt untergeht, da gibt es den Windows indexing service, der
den Inhalt von Dateien analysiert, damit man besser suchen kann (auch
wenn man das nie tut)...
--
Peter Below
TeamB
Christian Schmitt
2017-01-28 19:53:54 UTC
Permalink
Post by Peter Below
Das glaubst Du, aber der Glaube hat schon viele in die Irre geführt ;-).
Da gibt es Virenscanner, die jede neue Datei sofort scannen müssen, da
sonst die Welt untergeht, da gibt es den Windows indexing service, der
den Inhalt von Dateien analysiert, damit man besser suchen kann (auch
wenn man das nie tut)...
Ja stimmt, soweit habe ich auch nicht gedacht. Allerdings tritt das Problem auf einem neuen PC ohne Virenscanner auf. FileIndexing muß ich mal nachsehen, ob es standardmäßig bei Win10 eingeschaltet ist. Aber sind diese Dienste so "aggressiv", dass sie (Text)Dateien blockieren?
Hans-Peter Diettrich
2017-01-29 05:19:53 UTC
Permalink
Post by Peter Below
Da gibt es Virenscanner, die jede neue Datei sofort scannen müssen, da
sonst die Welt untergeht, da gibt es den Windows indexing service, der
den Inhalt von Dateien analysiert, damit man besser suchen kann (auch
wenn man das nie tut)...
Bis Win7 konnte ich den Indexdienst einfach abschalten, aber seitdem
geht gleichzeitig die Suchfunktion im Explorer verloren :-(

DoDi
Marc Santhoff
2017-01-28 11:51:15 UTC
Permalink
Post by Christian Schmitt
Ich habe eine Anwendung,
die auf Messages von extern reagiert. Jede Message wird dabei in eine
Logdatei geschrieben mittels einem TFileStream. Es kommen ca. 20.
Messages pro Sekunde an und hier und da kommt es dabei leider zu
Exception, dass die Logdatei gerade von einem anderen Programm in
Benutzung sei.
[...]

Finde raus, welches Programm an der Datei rumfummelt:

https://technet.microsoft.com/en-us/sysinternals/bb545046


Marc
Christian Schmitt
2017-01-28 19:54:40 UTC
Permalink
Post by Marc Santhoff
https://technet.microsoft.com/en-us/sysinternals/bb545046
Auch ne gute Idee, ich schaue mal nach...
Loading...