2011-01-06 169 views
3

我的程序需要從隨機訪問的巨大二進制文件中讀取塊。我有一個可能有數千個條目的偏移量和長度的列表。用戶選擇一個條目,程序尋找偏移量並讀取長度字節。在Delphi中讀取大文件的最快方法是什麼?

程序內部使用TMemoryStream來存儲和處理從文件中讀取的塊。讀取數據通過TFileStream的做過這樣的:

FileStream.Position := Offset; 
MemoryStream.CopyFrom(FileStream, Size); 

這工作得很好,但遺憾的是作爲文件變大就會變得越來越慢。文件大小從幾兆字節開始,但通常會達到幾十千兆字節。大塊讀取的大小約爲100千字節。

該文件的內容只能被我的程序讀取。這是當時唯一訪問該文件的程序。此外,文件存儲在本地,所以這不是一個網絡問題。

我在Windows XP上使用Delphi 2007。

我能做些什麼來加速這個文件訪問?

編輯:

  • 文件訪問是對大文件速度慢,不管是哪個文件的一部分被讀取。
  • 程序通常不會按順序讀取文件。塊的順序是由用戶驅動的,無法預測。
  • 從大文件中讀取塊總是比從小文件中讀取同樣大的塊要慢。
  • 我說的是從文件中讀取塊的性能,而不是處理整個文件所花費的總體時間。後者明顯需要更長的時間才能處理更大的文件,但這不是問題。

我需要道歉,大家:我使用內存映射文件來實現文件訪問後的建議事實證明,它並沒有多大的差別。但是在我添加了更多的時間代碼之後,我們發現它不是文件訪問會減慢程序的速度。無論文件大小如何,文件訪問實際上幾乎都是恆定的。用戶界面的某些部分(我尚未識別)似乎對大量數據有性能問題,但在某些情況下,我在第一次計算進程時看不到差異。

我很抱歉在識別瓶頸時馬虎。

+1

我沒有看到任何明顯的。這些流類只是系統文件I/O函數的包裝器。你如何能夠顯着提高隨機訪問模式的性能? – 2011-01-06 13:25:25

+0

你是說單次查找/讀取對用戶來說顯着較慢?或者這些操作的大批量「較慢」?如果數據來自磁盤,則無論文件大小如何,單個查找和讀取操作應該大致相同。使用7200轉的磁盤,應該可能在5到10毫秒之間。 – 2011-01-06 14:30:34

+0

這可能是內存碎片問題。你是否在操作之間釋放TMemoryStream?嘗試在應用程序的整個生命週期中保持活力,並觀察減速是否消失。 – 2011-01-06 14:36:26

回答

3

如果您打開CreateFile()WinAPI函數的幫助主題,您將在其中找到有趣的標誌,例如FILE_FLAG_NO_BUFFERING和FILE_FLAG_RANDOM_ACCESS。你可以和他們一起玩,以獲得一些表現。

接下來,複製文件數據,即使是100Kb的大小,也是一個額外的步驟,會降低操作速度。使用CreateFileMapping和MapViewOfFile函數來獲取準備好的指向數據的指針是一個好主意。這樣可以避免複製,並且可能會獲得一定的性能優勢(但您需要仔細測量速度)。

0

也許你可以採取這種做法:

排序上最大fileposition的條目,然後爲以下內容:

  1. 拿,只有需要的文件的第一個X MB(直到一定的條目fileposition)
  2. 讀取X MB從文件到緩衝區
  3. 重複此爲所有(內存流
  4. 現在從緩存(可能多線程讀取項)條目。

簡而言之:緩存文件的一部分,並閱讀安裝到它(multhithreaded)的所有條目,然後緩存在接下來的部分等

也許你能獲得速度,如果你只是把你原來的做法,但要對位置上的條目進行排序。

0

由於分配內存的方式,Delphi中的庫存TMemoryStream很慢。 NexusDB公司擁有更高效的TnxMemoryStream。那裏可能有一些免費的更好的工作。

股票德爾福TFileStream也不是最有效的組件。歷史上的回溯Julian Bucknall在雜誌或某處與文件流非常有效地合作的地方發佈了一個名爲BufferedFileStream的組件。

祝你好運。

相關問題