聊一聊 .NET高级调试 中的一些内存术语
一:背景
1. 讲故事
在高级调试的旅程中,经常会有一些朋友问我什么是
工作集(内存)
,什么是
提交大小
,什么是
Virtual Size
, 什么是
Working Set
。。。截图如下:
既然有很多朋友问,这些用口头也不怎么好描述,刚好上午有时间就系统的聊一下吧。
二:内存术语解读
1. Virtual Size 是什么
可能有些朋友知道,内存中的虚拟地址被划分成了三类。
- Reserved (预定地址)
- Committed (提交地址)
- Free (蛮荒地址)
上面的 预定+提交 就是我们的 Virtual Size,即
Virtual Size = Reserved + Committed
。
当然口说无凭,得要拿出证据,写一个 x86 的 C# 测试代码,参考如下:
static void Main(string[] args)
Console.WriteLine("hello world!");
Console.ReadLine();
将程序跑起来后用 windbg 附加,使用
!address -summary
将计算出的内存和
Process Explorer
工具显示的 Virtual Size 进行对比,截图如下:
有些较真的朋友可能说:Explorer 显示出的是
163.300
,而
windbg
显示的是
163.281
,为什么还差一点点,其实这是不同工具的统计误差,仅此而已。
2. Working Set
有些朋友可能知道,一个程序所占的内存最终会在三个地方落地:
- 物理内存条
- 虚拟内存 pagefile
- 物理文件 MappedFile
这里的
Workding Set
特指的就是
物理内存条
,由于 Windows 有 MappedFile 这种文件映射(内存共享)机制,所以物理内存条上的内存可以进一步划分为
自己独占的
+
大家共享的
,可能有些朋友比较蒙,截个图如下:
有了这张图的基础,转化为专业术语就是:
-
Workding Set
=WS Private
+WS Shareable
最后我们还是用 Explorer 观察下刚才的 C# 程序,截图如下:
3. Private Bytes
刚才我们说到了内存最终会落地到三个地方,其中一个地方就是
虚拟内存(pagefile)
,简而言之它的作用就是给物理内存打辅助,这个 pagefile.sys 默认是在 C 盘上,截图如下:
有了这些基础,就可以列出一个公式了。
-
Private Bytes
=WS Private
+Pages Out (pagefile)
上面的
Pages Out
是我定义的换页内存,这个
Private Bytes
指标在分析内存泄露的场景下特别有用,它能够准备的洞察当前程序是否存在大量的
Pages Out(换页内存)
。
为了方便演示出现了大量的换页内存,写一个不断灌数据的例子。
internal class Program
static void Main(string[] args)
var list = new List<string>();
for (int i = 0; i < 100000000; i++)
list.Add(string.Join(",", Enumerable.Range(0, 100000)));
if (i % 10000 == 0) { Console.WriteLine($"i={i}"); }
Console.WriteLine("成功!");
Console.ReadLine();
将程序跑起来后,截图如下:
根据刚才的计算公式:
Pages Out = Private Bytes - WS Private
,可以得知大概有 29G 不得不存放在 pagefile 中。
本来想用
wmic pagefile get /value
看一下当前机器的虚拟内存占用,发现有时候不准,我也没太深究了,输出如下:
C:\Users\Administrator>wmic pagefile get /value
AllocatedBaseSize=49464
Caption=C:\pagefile.sys
CurrentUsage=1473
Description=C:\pagefile.sys
InstallDate=20230807095038.481750+480