我有一个正在读取整个文件系统和散列文件的进程。它会减慢速度(大约 4 倍),因为读取会导致大量查找。每个文件的小块由 4 个线程中的每一个读取,但如果我通过复制 (cp) 测试顺序读取,我可以读取得更快。 CPU 利用率为 25%,因此不受 CPU 限制。我相当确定寻找是问题所在。
我读到内核有相当复杂的磁盘读取策略来加速访问,所以我想知道内核缓冲区是否限制了它们在这里的使用,以及是否可以增加它们以允许它缓冲更多。我假设我正在使用的程序在每次读取调用时仅请求相当小的数据块,所以我不知道这是否有效。
我想将每个文件完全一一读入内存将是最有效的,但我现在无法重写应用程序(它不是我的,而且在我看来它又大又臃肿)。但是,我能否让操作系统在每个文件完全(或什至部分地,例如一次 100 - 500MB)打开到缓冲区时按顺序读取每个文件,以便应用程序线程仅使用其每个小文件调用内存读取而不是调用磁盘(导致寻道)?
稍后添加:
@Artem 缓存似乎不能在这里完成工作,我想我可以理解为什么。内核试图表现得“明智”,并表示“我不会仅仅因为用户请求了第一个 MB,就将整个 500MB 文件读入内存”。这是有道理的。加载的内容确实会被缓存,因此如果再次使用它(例如由另一个进程),可以从内存中获取它。但我想要的是内核在第一次读取时将整个文件加载到缓存中(第一次读取是什么,也许是 2MB?)。
所以系统调用是read(fd, buf, size)。如果我正在编程,CI 永远不会放置一个巨大的缓冲区作为大小,我怀疑许多程序员会这样做。所以它可能是使用更正常的缓冲区大小(一兆或两兆)编写的。
因此,用户进程获得一或两个 MB 并进入哈希函数,这会使其忙碌一段时间,并停止纠缠内核进行磁盘读取。同时,另一个磁盘读取由不同的线程排队以读取磁盘的不同部分。因此,内核现在提供服务,并且磁盘寻找磁盘的不同部分,大约需要 15 毫秒。
遗憾的是,文件通常保存在磁盘上相当大的连续块中。因此,对第一个文件的磁盘持续读取可能会读取数十万个、甚至一百万个块、数十或数百 MB,而无需任何查找。高性能磁盘读取是我想要鼓励的。
但事实并非如此,进程正在请求小块数据,内核试图保持理智,不读取没有人请求的大量数据(这样做会阻止等待进程),并且结果,它疯狂地四处寻找,并花费了所有的时间去寻找。
与“cp -r”对比 - 只有 1 个线程要求内核读取文件。因此,没有人告诉磁盘头每 MB 或每 2 MB 寻找磁盘的不同部分,因此当后续读取进入内核时,驱动器能够快速获取数据。
代码可以用更大的缓冲区重写,所以这对我来说是一种选择。但正如我所说,我想知道是否可以指示内核“提前”缓冲更多。有点像“预读缓存”。预测文件一旦打开,将被完整读取,因此在停止物理磁盘读取每个文件的内核缓冲区之前,至少用 n 个字节填充读取缓冲区。
答案1
Linux 内核使用整个可用 RAM 来进行文件系统缓存。你不能让它使用更多。
您可以尝试使用更高的 swappiness 值,但我 99% 确定它不会有帮助。
可能您需要更多内存。