c - 使用 fgets 随机读取非常大的文件似乎会使 Windows 缓存达到极限

标签 c windows caching 64-bit large-files

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

我在阅读部分基本上做的是:(抱歉,非常短,可能有错误)

void seekAndGetLine(char* line, size_t lineSize, off64_t pos, FILE* filePointer){
  fseeko64(filePointer, pos, ios_base::beg);
  fgets(line, lineSize, filePointer);
}

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

另一个症状似乎是使用过的 RAM。我的进程保持它的 RAM 稳定,但系统使用的 RAM 有时会变得非常大。在使用了一些 RAM-Tools 之后,我发现 Windows 映射文件增长到几个 GB。这种行为似乎也取决于硬件,因为它发生在流程不同部分的不同机器上。

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

我的猜测是 Windows 缓存以某种方式变得“奇怪”。只要缓存正常工作,程序就会很快。但是当缓存出错时,行为要么进入“停止读取”要么进入“增加缓存大小”,有时甚至两者兼而有之。由于我不是 Windows 缓存算法方面的专家,我很乐意听到解释。另外,有什么方法可以让 Windows 脱离 C/C++ 来操作/停止/强制执行缓存。

由于我一直在寻找这个问题,所以我已经尝试了一些技巧,但没有成功:

  • filePointer = fopen(文件名, "rbR");//只是填充缓存直到RAM已满
  • 大量缓冲读/写,以阻止两者相互影响

提前致谢

最佳答案

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

有多个级别的缓存:

  • CRT 库(因为您使用的是 f- 函数)
  • 操作系统和文件系统
  • 可能在驱动器本身上

如果您通过 CRT 中的 f- 函数将 I/O 调用替换为 Windows API 中的类似函数(例如,CreateFile、ReadFile 等),则可以消除 CRT 缓存,这可能会造成更大的危害比好。您还可以警告操作系统您将进行随机访问,这会影响其缓存策略。查看 FILE_FLAG_RANDOM_ACCESS 等选项可能还有 FILE_FLAG_NO_BUFFERING .

您需要进行试验和测量。

您可能还需要重新考虑您的算法是如何工作的。搜索真的是随机的吗?您能否对它们重新排序,也许是分批处理,以便它们按顺序排列?您能否一次限制对文件中相对较小区域的访问?您能否将大文件分解成较小的文件,然后一次处理一个文件?您是否检查过驱动器和特定文件的碎片级别?

关于c - 使用 fgets 随机读取非常大的文件似乎会使 Windows 缓存达到极限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10853371/

相关文章:

c - 如何确定netbeans在命令行设置的环境变量

http - 如何先显示缓存的版本,然后再查看etag/modified-since?

c - 如何从未排序的数组中获取最小元素的索引?

c - C语言有什么方法可以通过变量来控制字符的长度吗?

c - c 中的 ')' token 错误之前预期为 '*'

c - 求串口读取例子

windows - 如何刷新 Matlab 窗口并将其保留在 Z 顺序中的位置

c - 无需套接字即可访问和管理 native Eth0

reactjs - Express.js : Set cache-control header for static assets bundled in webpack

java - 网络中最后一个值缓存的目的是什么?