Windows 任务管理器显示 VmmemWSL 占用 8 GB,Ubuntu 里 htop 只看到约 2 GB。作者 Thuram OTCHOUN 的结论是:问题不在工具,而在于两个数字不在同一个 scope 上,属于范畴错误。
WSL2 内存至少有四个层级:Windows 主机、WSL2 虚拟机(VmmemWSL)、单个 Linux 发行版、发行版内的单个进程。VM 层数字包含虚拟机自身、Linux 内核、缓存和各发行版负载;发行版层的 /proc/meminfo 只描述该环境所见;进程层的 ps、top、htop 只描述单个进程的内存映射。拿 8 GB 的 VM 数字去和 2 GB 的发行版数字对齐,本身就不成立。
把每个进程的 RSS 相加是看起来最直观、实际却错误的做法。RSS 不代表这些字节被该进程独占:共享库、共享内存、fork() 后写时复制之前的父子进程,都会让同一物理页出现在多个进程的 RSS 里。三个进程各报 30 MB、共享页 24 MB 时,sum(RSS) 是 90 MB,真实总量只有 42 MB,共享页被算了三次。规模放大后 sum(RSS) 甚至可能超过 VM 整体占用,用 VmmemWSL 减去它会得到负数。作者的结论是:进程内存是归因,不是总量;无法干净归因的部分应保留可见,而不是为了凑数被隐藏。
Linux 内部还有一层混淆。MemFree 只是当前未使用的内存,Linux 更愿意把空闲 RAM 用作文件系统页缓存,所以 MemFree 低并不等于内存有问题。要问系统在不立即陷入内存压力时还能腾出多少,MemAvailable 更有用,内核文档把它描述为计入可回收内核内存后、可供启动新应用的估计值。VM 又加了一层:VmmemWSL 回答的不是应用逻辑上用了多少内存,而是 Windows 看到的 WSL2 VM 当前占用,其中包含内核和缓存。
配置层同样容易被误读。[wsl2] 下的 memory=8GB 是分配给 VM 的上限,微软当前文档写明默认是 Windows 总内存的 50%;processors 默认等于 Windows 逻辑处理器数。上限是策略,实际用量是独立观测。autoMemoryReclaim 支持 disabled、gradual、dropCache 三种模式,当前文档以 dropCache 为默认;该功能最初是可选实验特性、默认 disabled,后来才改为 dropCache,旧文章给出的配置可能已不是当前默认。CPU 侧同理:/proc/loadavg 的前三个值是 1、5、15 分钟负载均值,按可运行任务和不可中断 I/O 任务定义,loadavg=4.0 既不等于 CPU 400%,也不等于 8 核机器上的 50%。
作者据此做了 Wisely,一个只读的 PowerShell 小工具,目的是让这些测量之间的差异难以被忽略:每个值标明所属 scope、来源、新鲜度,以及它是直接观测、归因、估计还是仅相关。它刻意拒绝把 sum(RSS) 包装成进程内存总量,拒绝把 loadavg 换算成 CPU 百分比,拒绝拿 VM 层数字去比发行版层阈值。作者称下一步不是加功能,而是先确认除自己之外是否真有人觉得它有用。