我的程序需要从随机访问的巨大二进制文件中读取块。我有一个偏移和长度列表,可能有几千个条目。用户选择一个条目,程序寻找偏移量并读取长度字节。
程序在内部使用TMemoryStream来存储和处理从文件中读取的块。读取数据是通过TFileStream完成的,如下所示:
FileStream.Position := Offset;
MemoryStream.CopyFrom(FileStream, Size);
这很好用,但不幸的是随着文件变大,它变得越来越慢。文件大小从几兆字节开始,但经常达到几十千兆字节。读取的块大小约为100千字节。
文件的内容仅由我的程序读取。它是当时唯一访问该文件的程序。此外,文件也存储在本地,因此这不是网络问题。
我在Windows XP盒子上使用Delphi 2007。
如何加快此文件访问速度?
编辑:
我需要向所有人道歉:我按照建议使用内存映射文件实现文件访问后发现它并没有太大的区别。但是在我添加了一些更多的时序代码之后,它也发现它不是文件访问速度会降低程序的速度。无论文件大小如何,文件访问实际上几乎都是恒定的时间。用户界面的某些部分(我尚未确定)似乎存在大量数据的性能问题,并且当我第一次对这些进程进行计时时,我看不出有什么不同。
我很遗憾地发现了瓶颈。
答案 0 :(得分:3)
如果您打开CreateFile()WinAPI函数的帮助主题,您会在那里找到有趣的标志,例如FILE_FLAG_NO_BUFFERING和FILE_FLAG_RANDOM_ACCESS。你可以和他们一起玩,以获得一些表现。
接下来,复制文件数据,即使是100Kb,也是一个额外的步骤,会减慢操作速度。使用CreateFileMapping和MapViewOfFile函数来获取指向数据的指针是一个好主意。这样您就可以避免复制,也可能获得一定的性能优势(但您需要仔细测量速度)。
答案 1 :(得分:0)
也许你可以采用这种方法:
对最大文件位置的条目进行排序,然后对以下内容进行排序:
简而言之:缓存文件的一部分并读取所有适合它的条目(multhithreaded),然后缓存下一部分等。
如果您采用原始方法,也许您可以获得速度,但可以根据位置对条目进行排序。
答案 2 :(得分:0)
由于分配内存的方式,Delphi中的TMemoryStream库存很慢。 NexusDB公司拥有更高效的TnxMemoryStream。可能会有一些免费的可以更好地工作。
股票Delphi TFileStream也不是最有效的组件。历史上的Wayback Julian Bucknall在杂志或某个地方发布了名为BufferedFileStream的组件,非常有效地处理文件流。
祝你好运。