Mein Programm muss Chunks aus einer riesigen Binärdatei mit wahlfreiem Zugriff lesen. Ich habe eine Liste von Offsets und Längen, die mehrere tausend Einträge haben können. Der Benutzer wählt einen Eintrag aus, und das Programm sucht nach dem Offset und liest Längenbytes.Was ist der schnellste Weg, um große Dateien in Delphi zu lesen?
Das Programm verwendet intern einen TMemoryStream, um die aus der Datei gelesenen Chunks zu speichern und zu verarbeiten. Lesen der Daten wird über eine TFileStream wie dies geschehen:
FileStream.Position := Offset;
MemoryStream.CopyFrom(FileStream, Size);
Dies funktioniert gut, aber leider wird es immer langsamer, da die Dateien größer werden. Die Dateigröße beginnt bei einigen Megabyte, erreicht aber häufig mehrere zehn Gigabyte. Die gelesenen Stücke sind ungefähr 100 kB groß.
Der Inhalt der Datei wird nur von meinem Programm gelesen. Es ist das einzige Programm, das zu der Zeit auf die Datei zugreift. Auch die Dateien werden lokal gespeichert, so dass dies kein Netzwerkproblem ist.
Ich verwende Delphi 2007 auf einer Windows XP-Box.
Was kann ich tun, um diesen Dateizugriff zu beschleunigen?
edit:
- Die Access-Datei ist langsam für große Dateien, unabhängig davon, welcher Teil der Datei gelesen wird.
- Das Programm liest die Datei normalerweise nicht sequenziell. Die Reihenfolge der Blöcke ist benutzergesteuert und kann nicht vorhergesagt werden.
- Es ist immer langsamer, einen Chunk aus einer großen Datei zu lesen, als einen gleich großen Chunk aus einer kleinen Datei zu lesen.
- Ich spreche über die Leistung für das Lesen eines Stücks aus der Datei, nicht über die Gesamtzeit, die es dauert, eine ganze Datei zu verarbeiten. Letzteres würde bei größeren Dateien natürlich länger dauern, aber das ist hier nicht das Problem.
Ich muss alle entschuldigen: Nachdem ich den Dateizugriff mit Hilfe eines Memory-Mapped-Datei implementiert, wie vorgeschlagen es stellte sich heraus, dass es nicht viel Unterschied gemacht hat. Aber es stellte sich auch heraus, nachdem ich etwas mehr Timing-Code hinzugefügt habe, dass es nicht der Dateizugriff ist, der das Programm verlangsamt. Der Dateizugriff dauert unabhängig von der Dateigröße nahezu konstant. Ein Teil der Benutzeroberfläche (die ich noch identifizieren muss) scheint ein Performance-Problem mit großen Datenmengen zu haben und irgendwie habe ich den Unterschied nicht gesehen, als ich die Prozesse zum ersten Mal gestartet habe.
Es tut mir leid, schlampig bei der Identifizierung des Engpasses zu sein.
Ich sehe nichts offensichtliches. Diese Stream-Klassen sind nur Wrapper um die Systemdatei-E/A-Funktionen. Wie können Sie die Zugriffsmuster für Random Access erheblich verbessern? –
Sie sagen, dass ein einzelnes Suchen/Lesen für den Benutzer spürbar langsamer ist? Oder dass ein großer "Batch" dieser Operationen langsamer ist? Eine einzelne Such- und Leseoperation sollte ungefähr gleich sein, unabhängig von der Dateigröße, wenn die Daten von der Platte kommen. Bei einer 7200 rpm-Disk sollte das zwischen 5 und 10 ms liegen. –
Es könnte sich um ein Speicherfragmentierungsproblem handeln. Befreien Sie den TMemoryStream zwischen den Operationen? Versuchen Sie, es für die gesamte Lebensdauer der Anwendung am Leben zu halten und zu sehen, ob die Verlangsamung verschwindet. –