强制目录始终位于缓存中


35

我一直在测试各种方法,以缩短编译整个c ++项目所需的时间。目前大约需要5分钟。我尝试了distcc,ccache等。最近,我发现,如果我将整个项目复制到RAM驱动器上,然后从那里进行编译,它将编译时间减少到原来的30%,即1.5分钟。

显然,从RAM驱动器工作是不切实际的。那么,有谁知道我可以强制操作系统始终保持某个目录缓存的方法吗?我仍然希望目录像往常一样被同步回磁盘,但是我也总是希望复制内存中的数据。这可能吗?

编辑: 作为一种可能的解决方案,我们只是想启动一个守护程序,该守护程序rsync每10秒左右运行一次,以将磁盘驱动器与RAM驱动器同步。然后,我们从RAM驱动器运行编译。该rsync是极快的,但这样做真的有用吗?当然,操作系统可以做得更好。


缓存不是tmpfs和ext3 / 4之间的唯一区别;例如,他们有日记,无论缓存如何,都会记录日记。
2011年

1
您能否time汇编并与我们分享结果?这将消除一些引起争议的问题。make clean && /usr/bin/time -v make(请勿使用内置的bash time命令)
shellholic 2011年

1
@she为什么不使用bash的内置命令?
tshepang 2011年

3
@Tshepang的time内置在bash( help time)有很多的细节较少(没有详细选项),比GNU时间(man time关于I / O),上下文切换,...
shellholic

Answers:


18

在缓存中保留一堆文件的明显方法是经常访问它们。Linux非常擅长在交换和缓存之间进行仲裁,因此我怀疑您观察到的速度差异实际上并不是由于操作系统未将内容保留在缓存中,而是由于您使用tmpfs与其他尝试之间的其他差异。

尝试观察每种情况下的IO。的基本工具是iotop。其他工具可能有用。通过文件系统路径和/或进程查看Linux磁盘IO负载故障?Linux中哪些程序可以随时间测量I / O?,以及“服务器故障”时的其他线程。

以下是关于可能发生的情况的一些假设。如果您进行测量,请显示它们,以便我们确认或反驳这些假设。

  • 如果您打开了文件访问时间,则操作系统可能会浪费大量时间来编写这些访问时间。访问时间对于编译树没有用,因此请确保使用noatimemount选项将其关闭。您的tmpfs + rsync解决方案永远不会从硬盘上读取数据,因此它永远不必花费额外的时间编写时间。
  • 如果写入是同步的(由于编译器调用sync()或内核频繁刷新其输出缓冲区),则写入硬盘所需的时间要比tmpfs更长。

我也有这种感觉。编译需要占用大量CPU,而不是IO。
phunehehe 2011年

嗯,我想在这里看到@JaredC的评论,以证实或否认Gilles的假设。1.5分和5分有很大的不同...
Daniel Alder

8

Linux 默认使用RAM作为磁盘缓存。作为演示,尝试运行time find /some/dir/containing/a/lot/of/files > /dev/null两次,第二次要快得多,因为每个磁盘inode都被缓存了。这里的重点是如何利用此内核功能并停止尝试替换它。

关键是要改变swappiness。让我们考虑三种主要的内存使用类型:活动程序,非活动程序和磁盘缓存。显然,活动程序使用的内存不应该交换出去,并且在其他两个程序之间进行选择是相当随意的。您要快速切换程序还是快速访问文件?一个低swappiness更愿意保留在内存中的程序(即使没有长期使用)和高swappiness喜欢保留更多的磁盘高速缓存(通过交换未使用的程序)。(swappiness scale为0到100,默认值为60)

我对您的问题的解决方案是将swappiness设置为很高(90-95而不是100)并加载缓存:

echo 95 | sudo tee /proc/sys/vm/swappiness > /dev/null # once after reboot
find /your/source/directory -type f -exec cat {} \; > /dev/null

如您所料,您必须有足够的可用内存来将所有源文件和目标文件以及编译器,包括的头文件,链接的库,IDE和其他使用的程序保存在缓存中。


通常,这很有用,但是我真正想要的是我的源代码具有较低的可交换性,而其他所有东西都具有正常的可交换性。本质上,我在后台进行了大量工作,但是我想将它们限制为8 GB中的6 GB,同时始终将其他2 GB用于源代码。我不想抓住它被交换的机会……永远……因为这很烦人。
JaredC'2

Swappiness是系统范围的。实际上,如果您正在执行其他操作,并且文件已从内存中卸载,则只需在第二行中重新加载它。如果必须为其他事情释放内存,那么您实际上就不会“想抓住机会”通过交换完成它。tmpfs在相同情况下,BTW 也将被交换掉。
shellholic 2011年

2
就我个人而言,我在工作站上掉得很高,简直太可怕了。尽管某些功能可能会通过更大的缓存(例如,更多的缓存文件)来加速,但这是有代价的:您需要在程序之间进行切换时以响应速度付费,这是用户在系统上工作时首先注意到的。当从浏览器切换到办公室的其他浏览器,电子邮件,我只是无法忍受不必等待1-2秒,每个节目交换回在我所有的Linux机器我通常设置swappiness至10低值。
fgysin恢复莫妮卡

6

强制缓存不是执行此操作的正确方法。最好将源保留在硬盘上,并在tmpfs上进行编译。许多构建系统,例如qmake和CMake,都支持源外构建。


6

inosync如果要同步到ramdisk,该守护进程听起来确实像您想要的那样。当文件更改时,它使用Linux的inotify工具而不是每隔10秒进行rsync同步。我在Debian存储库中找到了它作为inosync软件包,或者可以从http://bb.xnull.de/projects/inosync/获得其源代码。


听起来很有用。我会调查一下并报告。谢谢!
JaredC'2

5

如果我想将某些文件或所有文件保留在缓存中的某个目录中,那么这件事似乎对我有用。

vmtouch似乎只是在做事情。示例5可能有您需要的东西。

vmtouch -dl /whatever/directory/

我需要以root身份运行它 sudo


1
它看不到新的/已删除的文件。
六。

3

给定足够的内存,您从ramdisk上进行的构建将不进行I / O。这可以加快任何读取或写入文件的速度。I / O是最慢的操作之一。即使您在构建之前将所有内容都缓存了,尽管它们的影响很小,但仍然具有要写入的I / O。

通过将所有文件预加载到缓存中可能会提高速度,但是花费的时间应该包括在总的构建时间中。这可能不会给您带来太多优势。

将对象和中间文件构建到RAM中而不是磁盘中。进行增量构建可以使您在频繁构建上获得可观的收益。在大多数项目中,我会进行每日清洁构建,并在此之间进行增量构建。集成版本始终是干净的版本,但我尝试将它们限制为每天少于一个。

通过使用关闭了atime的ext2分区,可能会获得一些性能。您的源应该在日记文件系统(例如ext3 / 4)上的版本控制中。


2

如前所述,最明显的方法是读取您希望缓存的所有目录结构和文件内容。

您可以通过编写脚本来监视此输出vmstat 1(使用与您的操作系统相同的任何工具)并保持写入和读取的块数之和来自动执行此操作。一旦总和超过您选择的阈值,请读取要缓存的所有文件,重置总和,然后继续监视vmstat输出。为了快速读取文件:如果树中包含许多文件,请避免使用find ... -exec cat,而尝试find ... -print0 | xargs -0 cat使用不对每个文件执行cat的自定义程序。

监视磁盘IO优于使用固定间隔,因为监视磁盘IO会根据磁盘IO负载而发出或多或少地重新读取数据的信号。

我已经在需要快速读取索引文件的系统上成功使用了这种自动化方法,从而避免了硬盘I / O。我还使用strace列出了登录时访问的每个文件的列表,以便可以将所有内容保持在高速缓存中以进行快速登录。

这可能不是最佳解决方案,但非常适合我。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.