C 使用fgets随机读取非常大的文件似乎会带来Windows缓存';s极限

C 使用fgets随机读取非常大的文件似乎会带来Windows缓存';s极限,c,windows,caching,64-bit,large-files,C,Windows,Caching,64 Bit,Large Files,我已经为Windows7-64位编写了一个C/C++程序,可以处理非常大的文件。在最后一步中,它从输入文件(10GB+)中读取行,并将其写入输出文件。对输入文件的访问是随机的,写入是顺序的。 编辑:这种方法的主要原因是减少RAM的使用 在阅读部分,我基本上是这样做的:(对不起,非常简短,可能有问题) 通常这段代码很好,不是说快,但在一些非常特殊的条件下,它会变得非常慢。这种行为似乎不是确定性的,因为性能下降发生在文件其他部分的不同机器上,甚至根本没有发生。甚至到目前为止,程序完全停止读取,而没有

我已经为Windows7-64位编写了一个C/C++程序,可以处理非常大的文件。在最后一步中,它从输入文件(10GB+)中读取行,并将其写入输出文件。对输入文件的访问是随机的,写入是顺序的。 编辑:这种方法的主要原因是减少RAM的使用

在阅读部分,我基本上是这样做的:(对不起,非常简短,可能有问题)

通常这段代码很好,不是说快,但在一些非常特殊的条件下,它会变得非常慢。这种行为似乎不是确定性的,因为性能下降发生在文件其他部分的不同机器上,甚至根本没有发生。甚至到目前为止,程序完全停止读取,而没有光盘操作

另一个交响曲似乎是用过的公羊。我的进程使它的RAM保持稳定,但系统使用的RAM有时会增长得很大。在使用一些RAM工具后,我发现Windows映射文件会增长到几GB。这种行为似乎也取决于硬件,因为它发生在过程的不同部分的不同机器上

据我所知,SSD上不存在这个问题,所以它肯定和HDD的响应时间有关

我的猜测是Windows缓存在某种程度上变得“wierd”。只要缓存工作,程序就会运行得很快。但是,当缓存出错时,这种行为会变成“停止读取”或“增大缓存大小”,有时甚至两者兼而有之。由于我不是windows缓存算法的专家,我很乐意听到一个解释。还有,有没有办法让Windows脱离C/C++来操作/停止/强制执行缓存

由于我研究这个问题已经有一段时间了,我已经尝试了一些技巧,但没有成功:

  • filePointer=fopen(文件名,“rbR”)//只需填充缓存,直到RAM已满
  • 大量的读/写缓冲,以防止二者相互影响

提前感谢

对于任何缓存算法来说,对一个巨大的文件进行真正的随机访问是最糟糕的情况。最好关闭尽可能多的缓存

有多个级别的缓存:

  • CRT库(因为您使用的是f函数)
  • 操作系统和文件系统
  • 可能是驱动器本身
如果使用Windows API中的类似函数(例如CreateFile、ReadFile等)替换通过CRT中的f函数进行的I/O调用,则可以消除CRT缓存,这可能弊大于利。您还可以警告操作系统您将进行随机访问,这会影响其缓存策略。请参阅类似和可能的选项

你需要进行实验和测量


您可能还必须重新考虑您的算法是如何工作的。搜索真的是随机的吗?你能把它们重新排序吗,也许是分批排序,这样它们就排列整齐了?您可以一次限制对文件中相对较小区域的访问吗?你能把大文件分成小文件,然后一次处理一个文件吗?您检查过驱动器和特定文件的碎片级别了吗?

对于任何缓存算法来说,对一个大文件进行真正的随机访问都是最糟糕的情况。最好关闭尽可能多的缓存

有多个级别的缓存:

  • CRT库(因为您使用的是f函数)
  • 操作系统和文件系统
  • 可能是驱动器本身
如果使用Windows API中的类似函数(例如CreateFile、ReadFile等)替换通过CRT中的f函数进行的I/O调用,则可以消除CRT缓存,这可能弊大于利。您还可以警告操作系统您将进行随机访问,这会影响其缓存策略。请参阅类似和可能的选项

你需要进行实验和测量


您可能还必须重新考虑您的算法是如何工作的。搜索真的是随机的吗?你能把它们重新排序吗,也许是分批排序,这样它们就排列整齐了?您可以一次限制对文件中相对较小区域的访问吗?你能把大文件分成小文件,然后一次处理一个文件吗?您是否检查了驱动器和特定文件上的碎片级别?

根据应用程序所做的工作的大局,您可能会采取不同的方法-可能是这样的:

  • 确定需要从输入文件中选择哪些行并存储 列表中的行号
  • 对行号列表进行排序
  • 按顺序通读输入文件一次,然后拉出行 你需要(更好的是,寻找下一行并抓住它,特别是当有很大的差距时)
  • 如果要获取的行列表足够小,则可以存储 在输出之前,请将它们保存在内存中以便重新排序,否则,请粘贴它们 在较小的临时文件中,并将该文件用作 为最终输出重新排列行的当前算法

  • 这无疑是一种更复杂的方法,但它会对缓存子系统更友好,因此可能会有更好的性能。

    根据应用程序的总体情况,您可能会采取不同的方法-可能是这样的:

  • 确定需要从输入文件中选择哪些行并存储 列表中的行号
  • 对行号列表进行排序
  • 按顺序通读输入文件一次,然后拉出行 你需要(更好的是,寻找下一行并抓住它,特别是当有很大的差距时)
  • 如果要获取的行列表足够小,则可以存储 在输出之前,请将它们保存在内存中以便重新排序,否则,请粘贴它们 在较小的临时文件中,并将该文件用作
    void seekAndGetLine(char* line, size_t lineSize, off64_t pos, FILE* filePointer){
      fseeko64(filePointer, pos, ios_base::beg);
      fgets(line, lineSize, filePointer);
    }