我们有一个 OSv 项目的测试平台,该项目多次运行(5.15.0-72-generic - 20.04.1-Ubuntu - x86_64)相同的实例。执行单次运行的脚本非常简单,如下所示:
while [ $x -le $t ]
do
./scripts/capstan_run.sh "$delay"
now="$(date +'%d%m%Y-%H%M%S')"
./scripts/stats.sh > stats/"$x"_"$delay"_stats_"$now".txt & PID=$!
sleep "$delay" #sleep delay mills for the execution
kill $PID ; wait $PID 2>/dev/null
echo "Delay $delay before fetches"
sleep "$delay" #sleep delay mills before fetch files
./scripts/fetch_files.sh "$delay"
./scripts/shutdown_vm.sh
((x++))
done
capstun_run.sh
使用在 QEMU 虚拟化层上执行的容器启动模拟。然后它会休眠并从实例中检索文件。该shutdown.sh
脚本终止 QEMU:
killall qemu-system-x86_64
我们观察到运行之间使用的内存有所增加。它是恒定的并且永远不会减少。该服务器有 126G RAM 和 24 个 CPU。
例如,我们观察到已用内存从 8% 开始到 12%,增量为 0.1%。
Date Memory Disk CPU
...
07/04/2023-163242 12.03% 27% 15.00%
07/04/2023-163247 12.03% 27% 16.00%
07/04/2023-163252 12.03% 27% 16.00%
07/04/2023-163257 12.03% 27% 16.00%
07/04/2023-163303 12.03% 27% 16.00%
07/04/2023-163308 12.04% 27% 16.00%
07/04/2023-163313 12.03% 27% 16.00%
07/04/2023-163318 12.04% 27% 15.00%
07/04/2023-163323 12.04% 27% 16.00%
07/04/2023-163328 12.04% 27% 16.00%
07/04/2023-163334 12.04% 27% 16.00%
07/04/2023-163339 12.04% 27% 16.00%
07/04/2023-163344 12.06% 27% 16.00%
07/04/2023-163349 12.08% 27% 16.00%
07/04/2023-163354 12.09% 27% 16.00%
07/04/2023-163359 12.09% 27% 15.00%
07/04/2023-163405 12.09% 27% 15.00%
07/04/2023-163410 12.09% 27% 15.00%
07/04/2023-163415 12.09% 27% 15.00%
QEMU是否存在内存泄漏?
===更新===
stats.sh 按以下方式计算已使用的 % mem:
free -m | awk 'NR==2{printf "%.2f%%\t\t", $3*100/$2 }
所以我认为有一个错误,因为它的“used/total*100”e不包括缓存。
我的评价正确吗?
答案1
如果 QEMU 进程已终止,则内核已释放其正在使用的所有内存。其自身地址空间内的任何内存泄漏都不会在进程自身终止后继续存在。您更有可能看到用于缓存的内存。该内存用于提高性能,并且可以在需要时随时回收。用于缓存的内存通常不会增加内存压力。
尽管可能性不大,但 QEMU 有可能在其虚拟地址空间之外分配内存,例如在 tmpfs 中(虽然它算作缓存内存,但不能删除)。进程可以通过多种方式使用未自动释放的资源,或导致其他进程泄漏资源,例如无法关闭文件描述符。如果不了解有关如何使用 QEMU 的更多信息,则无法确定是否是这种情况,但可能性不大。
您应该使用 的“可用”字段free
,而不是“已使用”字段。虽然后者减去了缓存,但某些被视为缓存内存的内存无法回收。曾经的田野,2014年添加,是真正可用的内存的更准确表示:
许多负载平衡和工作负载放置程序都会检查 /proc/meminfo 以估计有多少可用内存。他们通常通过将“免费”和“缓存”相加来做到这一点,这在十年前还不错,但今天几乎肯定是错误的。
这是错误的,因为 Cached 包含不可作为页面缓存释放的内存,例如共享内存段、tmpfs 和 ramfs,并且它不包含可回收的平板内存,在大多数空闲的系统上,这些内存可能会占用大部分系统内存很多文件。
您应该awk
用以下内容替换您的行:
awk '$1 == "MemTotal:" {total=$2} $1 == "MemAvailable:" {avail=$2} END {printf "%.2f%%\t\t", (avail/total)*100}' < /proc/meminfo
除了使用可用内存进行计算之外,它还使用/proc/meminfo
而不是free
,它具有稳定(可预测)的格式并且旨在机器可读。