我们的嵌入式 (Arm) linux 产品在一夜之间被锁定,但无法将其固定下来。从通电开始,问题通常需要 12-16 小时才能显现出来。我已经安装了 sysstat,所以我可以运行 sar 日志记录,并且我有一堆数据,但我无法解释结果。
目标只有 512Mb RAM(我们有其他型号有 1Gb,但他们很少看到这个问题),并且没有磁盘交换文件以避免磨损 eMMC。
某种分页/虚拟内存事件引发了问题。在 sar 日志中,pgpin/s、pgnscand/s 和 pgsteal/s 和 majflt/s 在滚雪球到疯狂水平之前都在稳步增长。这使 CPU 处于相应的高水平(双核 Arm 芯片上为 30-60)。同时,frmpg/s 值非常负,而 campg/s 非常正。结果是系统试图一次分配大量缓存页面。我不明白为什么会这样。
然后目标基本上锁定,直到它重新启动或有人杀死主 GUI 进程或它崩溃并重新启动(我们有一个一直运行的单片 GUI 应用程序,通常在产品上完成所有严肃的工作)。网络关闭,telnet 永远阻塞,就像 /proc 文件系统查询和依赖它的东西一样。此测试中主应用程序的内存分配配置文件主要通过从文件中读取数据并将其作为纹理缓存在使用 OpenGL ES 2.0 的 LRU 中的视频内存(与主 RAM 共享)中。大多数情况下,它将访问单个文件(它们的大小约为 50Mb),但我想它可能是由于不得不突然使用一个新文件并尝试一次性缓存所有 50Mb 文件而触发的。我没有
奇怪的是,实际的空闲和缓存 RAM 级别并没有显示出明显的内存不足(我已经看到 oom-killer 在杀死具有 > 100Mb 空闲和 40Mb 缓存 RAM 的主应用程序时突然出现)。主应用程序的内存使用情况似乎相当不错,而 VmRSS 值似乎相当稳定。Valgrind 没有发现任何在操作过程中会发生的渐进式泄漏。
这种行为似乎是系统疯狂地换出磁盘并因此使一切运行缓慢,但我不知道这是否是免费<->缓存 RAM 交换系统中的已知效果。
我的问题表面上类似于问题:linux high kernel cpu usage on memory initialization但这个问题似乎是由磁盘交换文件管理驱动的。但是,对于我的问题,脏页刷新似乎是合理的。
我还没有尝试过使用 /proc/sys/vm 下的各种 vm 文件。vfs_cache_pressure 和可能的 swappiness 似乎是一些调整的好选择,但我想了解一些好的值来尝试这里。vfs_cache_pressure 似乎没有明确定义将其设置为 200 与 10000 之间的区别是多少。
另一个有趣的事实是,这是一个渐进的问题。第一次出现效果可能需要 12 小时。如果主应用程序被杀死并重新启动,它似乎每 3 小时发生一次。不过,完整的缓存清除可能会将其推出。
这是日志数据的链接,其中包含两个文件 sar1.log,它是 sar -A 的完整输出,以及 overview.log,它是空闲/缓存内存、CPU 负载、MainGuiApp 内存统计信息的提取,以及 -B 和-R sar 输出午夜到凌晨 3:40 之间有趣的时间段:
https://drive.google.com/folderview?id=0B615EGF3fosPZ2kwUDlURk1XNFE&usp=sharing
所以,总而言之,我在这里最好的计划是什么?调整 vm 以更频繁地回收页面以减少突发性?考虑到日志数据,我对正在发生的事情的假设是否有效?有没有更聪明的方法来处理这种内存使用模型?
谢谢你的帮助。
2013 年 6 月 5 日更新: 我尝试了蛮力方法,并在其上放置了一个脚本,每小时将 3 回显到 drop_caches。这似乎正在维持系统的稳定状态,并且 sar -B 统计数据保持在平坦部分,几乎没有重大故障和 0.0 pgscand/s。但是,我不明白为什么将缓存 RAM 保持在非常低的水平可以缓解内核试图将宇宙添加到缓存 RAM 的问题。