在内存文件中使用

Working with in memory file

本文关键字:文件 内存      更新时间:2023-10-16

据我了解,如果我们加载任何文件一次进行读取,那么它就会按照 LRU 算法保留在 RAM 中,直到不被其他文件交换。

在我的 C 程序中,我正在加载 124MB 的文本文件来读取它的内容。理想情况下,一旦我执行它应该在 RAM 中,下次当我很快执行相同的程序时,它应该只从 RAM 中获取它。

但是在这两种情况下花费的时间只有 15 秒,而不考虑我执行同一程序的时间。

由于缓存大小非常有限,例如 3MB,因此无法放入缓存。

还有

什么其他选择来加快程序执行?

更新:

代码链接 :

http://webdocs.cs.ualberta.ca/~sajib/cmput606/project/code/svm_classify.c - 此文件包含 main(( 类并执行分类作业

http://webdocs.cs.ualberta.ca/~sajib/cmput606/project/code/svm_common.c - 此文件包含用于读取文件和执行分类的功能

首次读取文件后,在正常配置的操作系统下,很可能有效地缓存了所涉及的磁盘页面。

假设其他进程不需要此内存,第二次读取将比第一次读取快得多。

作为快速测试,我们生成一个随机文件并计算两次 md5sum(在 Linux 中的示例(:

$ dd if=/dev/urandom of=/tmp/readtest count=124 bs=1M
$ echo 3 > /proc/sys/vm/drop_caches  # needs to be run as root
$ time md5sum /tmp/readtest 
f788abe8a8d120a87bb293e65e5d50ff  /tmp/readtest
real    0m5.706s
user    0m0.332s
sys 0m0.072s
$ time md5sum /tmp/readtest 
f788abe8a8d120a87bb293e65e5d50ff  /tmp/readtest
real    0m0.295s
user    0m0.268s
sys 0m0.024s

观察删除缓存页面后的巨大差异。

您可能不欣赏这一点的原因如下:

  • 该文件实际上在您第一次读取时已经缓存(很可能(
  • 此磁盘或分区禁用缓存,或者文件系统/设备不支持缓存(非常不可能(。

在体面的 SSD 上加载 120MB 文件应该需要不到 1 秒的时间。 硬盘需要 2-3 秒。 我可以假设您不是以大块读取文件,而是使用标准库中的功能以小增量读取它(例如 fscanf或使用fstream (。

尝试以大块 (1-16MB( 读取文件,并在该缓冲区上进行处理。

如果读取文件时有大量 I/O 调用,则由于从内核模式到用户模式和其他要求 I/O 的进程来回切换,会产生大量开销。

编辑: 很多电话给fscanfgets。尝试将整个文件读取到单个缓冲区并使用该缓冲区。使用read(不是fread(一次性读取文件。

如果文件太大,请将其拆分为 1MB 读取。

编辑2

在函数中read_modelfscanf替换为sscanf以处理缓冲区。
一次性将所有模型读取到文件大小的大缓冲区。文件大小可以使用stat找到。 不使用fgets而是使用 strtok 迭代缓冲区。 后者可用于在迭代新行时用 NULL 字符替换新行。

如果您不知道这些功能中的任何一个,请尝试在谷歌上搜索man funcname。 例如 man strktok .

如果您将文件作为一个整体读取,则如果您的操作系统缓存该文件,该文件将位于 RAM 中。如果在两次运行之间,缓存压力使您的操作系统(例如 Linux 内核(丢弃加载的文件,您的文件将再次从磁盘读取它。

但是,程序无法控制文件是否来自缓存。操作系统为您的程序提供文件,无论是来自磁盘还是从文件缓存都超出了您的控制范围。

可以在这篇小文章中找到更多信息:Linux 磁盘缓存的实验和乐趣