当我运行使用大部分 16GB 物理内存的应用程序时,Linux 内核会交换内存中的大部分页面。应用程序完成后,每个操作(输入命令、切换工作区、打开新网页等)都需要很长时间才能完成,因为首先需要从交换中读回相关页面。
有没有办法告诉 Linux 内核将页面从交换区复制回物理内存,而无需手动触摸(并等待)每个应用程序?我运行了很多应用程序,所以等待总是很痛苦。
我经常用来swapoff -a && swapon -a
使系统再次响应,但这会清除交换中的页面,因此下次运行脚本时需要再次写入它们。
是否有一个内核接口(也许使用 sysfs)来指示内核从交换区读取所有页面?
编辑:我确实在寻找一种方法来使所有交换交换缓存。 (谢谢德罗伯特!)
[PS serverfault.com/questions/153946/...和serverfault.com/questions/100448/…是相关主题,但没有解决如何让 Linux 内核将页面从交换区复制回内存而不清除交换区的问题。]
答案1
它可能会有所帮助/proc/sys/vm/page-cluster
(默认值:3)。
来自内核文档(sysctl/vm.txt
):
页簇
page-cluster 控制单次尝试从交换中读入连续页面的页数。这是页面缓存预读的交换对应项。提到的连续性不是指虚拟/物理地址,而是交换空间上的连续性 - 这意味着它们被一起交换。
它是一个对数值 - 将其设置为零表示“1 页”,将其设置为 1 表示“2 页”,将其设置为 2 表示“4 页”等。零会完全禁用交换预读。
默认值为三(一次八页)。如果您的工作负载是交换密集型的,则将其调整为不同的值可能会带来一些小好处。
较低的值意味着初始故障的延迟较低,但同时会出现额外的故障和后续故障的 I/O 延迟(如果它们是预读的连续页的一部分)。
该文档没有提到限制,因此您可能可以将其设置得高得离谱,以使所有交换很快被读回。当然,之后将其恢复到正常值。
答案2
在我看来,你不能神奇地“让系统再次响应”。您要么立即遭受惩罚,要么将页面从交换空间读回到内存中,或者稍后遭受惩罚,但无论哪种方式都会引起它。事实上,如果你做了类似的事情swapoff -a && swapon -a
,你可能会觉得更多的痛苦而不是减少,因为您强制将某些页面复制回内存,否则这些页面将不再需要,并最终在不被读取的情况下被删除(想一想:您退出应用程序,而其大部分堆被换出;这些页面可以被完全丢弃而没有读回内存)。
但这会清除交换页面,因此下次运行脚本时需要再次写入它们。
好吧,几乎任何从交换区复制回主内存的页面都会被修改,因此如果将来需要将其移回交换区,则无论如何都必须将其重新写入交换区。请记住,交换区主要是堆内存,而不是只读页面(通常由文件支持)。
我认为你的swapoff -a && swapon -a
伎俩与你能想出的任何东西一样好。
答案3
基于内存转储程序最初发现这里我创建了一个脚本来有选择地将指定的应用程序读回内存。remember
:
#!/bin/bash
declare -A Q
for i in "$@"; do
E=$(readlink /proc/$i/exe);
if [ -z "$E" ]; then
#echo skipped $i;
continue;
fi
if echo $E | grep -qF memdump; then
#echo skipped $i >&2;
continue;
fi
if [ -n "${Q[${E}]}" ]; then
#echo already $i >&2;
continue;
fi
echo "$i $E" >&2
memdump $i 2> /dev/null
Q[$E]=$i
done | pv -c -i 2 > /dev/null
用法:类似
# ./remember $(< /mnt/cgroup/tasks )
1 /sbin/init
882 /bin/bash
1301 /usr/bin/hexchat
...
2.21GiB 0:00:02 [ 1.1GiB/s] [ <=> ]
...
6838 /sbin/agetty
11.6GiB 0:00:10 [1.16GiB/s] [ <=> ]
...
23.7GiB 0:00:38 [ 637MiB/s] [ <=> ]
#
它会快速跳过非交换内存(每秒千兆字节),并在需要交换时减慢速度。
答案4
这里有一个非常好的讨论http://rudd-o.com/en/linux-and-free-software/tales-from-responsivenessland-why-linux-feels-slow-and-how-to-fix-that 这归结为减少交换性,其想法是为了提高系统的感知响应能力,应该防止交换代码(这就是发生的情况)。这并不是您问题的真正答案,但这可能会防止问题出现(您的应用程序不会被交换,只有未使用的数据和页面缓存)