我有一个巨大的 Mercurial 存储库(猜猜它有多少目录——它会比你想象的还要多)。执行基本存储库操作所需的时间在很大程度上取决于系统缓冲区高速缓存是热还是冷,如以下示例所示(一个命令在另一个命令之后运行):
bash> time hg status
real 0m41.809s
user 0m0.815s
sys 0m0.217s
bash> time hg status
real 0m0.858s
user 0m0.679s
sys 0m0.175s
当我几天不使用机器(没有重新启动)后,我发现缓存变冷了,并且再次运行需要很长时间hg status
。尽管没有或很少有目录发生更改(通过检查 mtimes 进行验证)并且具有大量 RAM(甚至计算页面缓存也没有全部使用;使用 进行验证free
)。
那么既然没有内存压力,为什么东西会从 dentry 或 inode 缓存中被逐出呢?他们在某处有最大尺寸吗?有趣的是,我从未见过free
超过 4 GB 的“缓冲区”列。不确定系统是否拒绝让缓冲区缓存增长得大于此值。
答案1
对于目录遍历最重要的缓存是 inode 缓存。这不包含在free
显示的“缓存”图中。它是内核数据的一部分(“平板”)。您可以看到各个slab池占用了多少内存/proc/slabinfo
(这需要root访问权限)。您可以使用slabtop
查看它们实时变化,或者使用此代码片段获取每个池大小(以字节为单位)的报告:
</proc/slabinfo awk '{print $1, $3*$4}' |sort -k2n
在典型的机器上,inode 缓存的压力来自夜间更新数据库工作。如果您找到避免这种情况的方法,让我知道。
inode缓存池的大小不是固定的,它由元数据缓存与数据缓存的比例决定:vm.vfs_cache_pressure
范围。您可能想尝试一下 - 要么使用较低的值(默认为 100)以在缓存中保留更多条目,以便来自夜间 cron 作业的条目hg
不会被替换,要么使用较高的值,以便来自夜间 cron 作业的条目不会被替换。留下来污染RAM。
hg status
最后,总是有在早上的 cron 作业中运行的技巧。