在Delphi中读取大文件的最快方法是什么?
我的程序需要从随机访问的巨大二进制文件中读取块。我有一个可能有数千个条目的偏移量和长度的列表。用户选择一个条目,程序寻找偏移量并读取长度字节。在Delphi中读取大文件的最快方法是什么?
程序内部使用TMemoryStream来存储和处理从文件中读取的块。读取数据通过TFileStream的做过这样的:
FileStream.Position := Offset;
MemoryStream.CopyFrom(FileStream, Size);
这工作得很好,但遗憾的是作为文件变大就会变得越来越慢。文件大小从几兆字节开始,但通常会达到几十千兆字节。大块读取的大小约为100千字节。
该文件的内容只能被我的程序读取。这是当时唯一访问该文件的程序。此外,文件存储在本地,所以这不是一个网络问题。
我在Windows XP上使用Delphi 2007。
我能做些什么来加速这个文件访问?
编辑:
- 文件访问是对大文件速度慢,不管是哪个文件的一部分被读取。
- 程序通常不会按顺序读取文件。块的顺序是由用户驱动的,无法预测。
- 从大文件中读取块总是比从小文件中读取同样大的块要慢。
- 我说的是从文件中读取块的性能,而不是处理整个文件所花费的总体时间。后者明显需要更长的时间才能处理更大的文件,但这不是问题。
我需要道歉,大家:我使用内存映射文件来实现文件访问后的建议事实证明,它并没有多大的差别。但是在我添加了更多的时间代码之后,我们发现它不是文件访问会减慢程序的速度。无论文件大小如何,文件访问实际上几乎都是恒定的。用户界面的某些部分(我尚未识别)似乎对大量数据有性能问题,但在某些情况下,我在第一次计算进程时看不到差异。
我很抱歉在识别瓶颈时马虎。
如果您打开CreateFile()WinAPI函数的帮助主题,您将在其中找到有趣的标志,例如FILE_FLAG_NO_BUFFERING和FILE_FLAG_RANDOM_ACCESS。你可以和他们一起玩,以获得一些表现。
接下来,复制文件数据,即使是100Kb的大小,也是一个额外的步骤,会降低操作速度。使用CreateFileMapping和MapViewOfFile函数来获取准备好的指向数据的指针是一个好主意。这样可以避免复制,并且可能会获得一定的性能优势(但您需要仔细测量速度)。
也许你可以采取这种做法:
排序上最大fileposition的条目,然后为以下内容:
- 拿,只有需要的文件的第一个X MB(直到一定的条目fileposition)
- 读取X MB从文件到缓冲区
- 重复此为所有(内存流
- 现在从缓存(可能多线程读取项)条目。
简而言之:缓存文件的一部分,并阅读安装到它(multhithreaded)的所有条目,然后缓存在接下来的部分等
也许你能获得速度,如果你只是把你原来的做法,但要对位置上的条目进行排序。
由于分配内存的方式,Delphi中的库存TMemoryStream很慢。 NexusDB公司拥有更高效的TnxMemoryStream。那里可能有一些免费的更好的工作。
股票德尔福TFileStream也不是最有效的组件。历史上的回溯Julian Bucknall在杂志或某处与文件流非常有效地合作的地方发布了一个名为BufferedFileStream的组件。
祝你好运。
我没有看到任何明显的。这些流类只是系统文件I/O函数的包装器。你如何能够显着提高随机访问模式的性能? – 2011-01-06 13:25:25
你是说单次查找/读取对用户来说显着较慢?或者这些操作的大批量“较慢”?如果数据来自磁盘,则无论文件大小如何,单个查找和读取操作应该大致相同。使用7200转的磁盘,应该可能在5到10毫秒之间。 – 2011-01-06 14:30:34
这可能是内存碎片问题。你是否在操作之间释放TMemoryStream?尝试在应用程序的整个生命周期中保持活力,并观察减速是否消失。 – 2011-01-06 14:36:26