2010-02-28 70 views
2

我希望我的代码能够非常快速地处理文件。此文件大小将从单个KB到甚至2 GB不等。需要快速文件访问选项

即使我准备为该单个文件创建单独的文件系统。

我会将文件分割为常量大小的块(可能为8KB)并访问它以进行数据读取和写入。代码明智的是,该算法不能改变,因为它提供了良好的性能和稳定的性能。所以我不想改变。我也使用mmap()将块按需映射到内存。

是否有可能将文件系统作为单个块来读取文件,读写操作可以更快?

请给出你的所有建议,即使是一个小东西,这将帮助我。

建议可以跨平台和文件系统。

感谢, 娜迦

+1

你打算使用什么操作系统?什么语言? – 2010-02-28 07:10:46

+0

我的代码应该可以跨OS使用。为了简单起见,我想在Linux(Fedora 11)中实现您的建议,我使用的是C语言。 – Naga 2010-02-28 07:45:05

回答

0

mmapMapViewOfFile让你直接访问内存中的文件。操作系统将根据需要透明地在页面中出错,或者甚至可能提前读取(可以用madviseFILE_FLAG_*来暗示)。根据您的访问模式和文件大小,这可能比读取/写入文件通常快得多。

不利的一面是,您将不得不担心一致性问题(请务必谨慎使用msyncFlushViewOfFile),并且由于必需的可分页操作,它可能也会变得更慢。

+0

我明白mmap()将会是更好的选择,因此我正在使用它。现在我将文件分割为8k块。是否有任何硬块和快速的块大小规则?示例:如果我访问某个特定的块,则会加载单页错误。 – Naga 2010-02-28 08:26:43

+0

目前大多数常见平台上的块大小为4kB或8kB,尽管http://linux-mm.org/HugePages Linux可以让你'mmap(... MAP_HUGETLB ...)'这可能会给你2MB或4MB的页面;有了这个,页面错误就会减少,但每个页面都会花费更长时间才能满足。并且不要认为操作系统只按需要映射页面,然后将它们留在它们周围:它可能会提前读取并抢先映射更多页面,或者它可能会丢弃它需要/想要驱逐的页面。在你自己的系统上做自己的实验,结果*会根据许多因素而变化。 – ephemient 2010-02-28 08:53:29

0

Windows允许您打开原始读取和写入的分区。它也可以让你打开一个原始IO的物理设备。因此,如果您愿意将硬盘或分区视为单个文件,则可以保证“文件”在磁盘上在逻辑上连续。 (由于硬盘对坏扇区执行修补程序的方式,实际上可能不是物理上连续)。

如果您选择做原始io,那么您将不得不读取和写入设备块大小的倍数。这通常是512字节,但将4k用作块大小可能会更明智一些,因为这是更新的磁盘正在使用的内容,也就是Win32的页面大小。

要打开原始读取的分区,请使用文件名为“\。\ X:”的CreateFile,其中X:是分区的驱动器号。参见下节标题物理磁盘和卷

在另一方面的CreateFile文档,这是相当难打的内存性能映射文件,看到这个问题的一个例子 How to scan through really huge files on disk?

+0

我明白mmap()将会是更好的选择,因此我正在使用它。现在我将文件分割为8k块。是否有任何硬块和快速的块大小规则?示例:如果我访问某个特定的块,则会加载单页错误。 – Naga 2010-02-28 08:27:03

0

总是试图以64kB-1MB为单位顺序访问您的文件。这样,您就可以利用预取并最大化每个I/O操作的数据量。

此外,请尝试确保文件首先是连续的,以便磁盘头不必在连续读取之间移动很多。如果您通过设置文件末尾或一次执行整个文件的步骤开始,许多文件系统将创建尽可能连续的文件。在Windows上,您可以使用sysinternals.com实用程序contig.exe使文件连续。

1

通用,独立于操作系统的一般规则:

  • 使用物理读取(而不是 流)

  • 使用您的读取大I/O缓冲区。 I/O操作的初始化(以及与旋转硬件的同步)是花费时间的。几个小的阅读需要比一个大的阅读长。

  • 创建一些基准来找出最有效的缓冲区大小。在给定尺寸之后,效率不会提高,而且您不希望无用地吞噬所有珍贵的RAM。最佳缓冲区大小取决于您的硬件和操作系统。在当前的硬件上,使用500KB到1MB范围内的缓冲区大小通常足够有效。

  • 最小化磁头寻找。即如果必须将数据写回,则读/写交替可能会非常昂贵(如果它们属于同一物理磁盘)。

  • 如果你有一些重要的处理要做,使用双缓冲和异步IO重叠IO和处理。