由于某种原因,我们的系统在使用内存约为 60GB 时开始交换(主动使用的内存)。(参见下面的编辑,似乎 I/O 和磁盘缓存的使用情况,甚至以前运行的进程都有影响)关闭它(swapoff-a
)进行测试导致 bad_alloc 一次(我猜是因为当时有更多进程也在使用内存)但也使我的程序速度提高了 10 倍以上。
这重现了该问题(没有其他重要进程运行,编辑:参见下文,仅当 I/O 密集型进程之前不久运行才会发生这种情况):
#include <cstdio>
#include <vector>
int main() {
size_t bytes = size_t(80) * 1024 * 1024 * 1024; // 80GB
size_t* data = new size_t[bytes / sizeof(size_t)];
for (size_t i = 0; i < bytes / sizeof(size_t); ++i) {
data[i] = i;
}
for (;;) {}
}
在使用内存约 60GB 时,系统开始交换,CPU 使用率降至 100% 以下(我猜是因为该过程现在受 I/O 限制)。
系统是Ubuntu 14.04,64位:
Linux ... 3.13.0-77-generic #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
一旦达到这一点,free -m 将给我以下结果:
total used free shared buff/cache available
Mem: 96671 55504 358 60 40808 40478
Swap: 47679 19366 28313
当 swappiness=1 时问题仍然存在(如果刚刚运行了 I/O 密集型程序,尤其是对于我的实际罪魁祸首(不是上面的代码)来说,它同时执行了大量的 I/O 并使用了大量的内存。如果最近几乎没有 I/O,则上述程序将分配所有内存并且不会交换!
如果长时间内没有 I/O 密集型操作,问题就会消失。似乎操作系统以某种方式使我的应用程序进行交换,因为它认为磁盘缓存更有价值 - 即使在交换量非常低的情况下也是如此。我不明白这种行为,因为磁盘缓存内存应该与可用内存一样好,而且肯定不会在正在运行的进程上触发交换。
最初,我的问题发生在一个读取大文件并占用大量内存的应用程序中。之后,它一直持续到上面根本没有 I/O 的示例代码。最后,当我稍后启动示例代码时,没有发生交换。
答案1
64 GB 似乎是支持 PAE 的 32 位 Ubuntu 的极限: https://help.ubuntu.com/community/32bit_and_64bit
32 位计算机的字长为 32 位,理论上内存限制为 4GB。通过使用“物理地址扩展”(PAE),这一限制得到了扩展,将限制提高到 64GB,尽管 4GB 以上的内存访问速度会略慢。
答案2
检查vmstat
一下si
,so
(交换入/出)是否真的填充了任何交换。即使将 swappiness 设置为 0,交换也可以分配交换。