内存工作设置(工作集)、提交大小概念简述

内存工作设置(工作集)、提交大小概念简述

前言

Windows7的任务管理器(以中文版为例)里面"进程"Tab页的列里面跟内存相关的展示项有7项(分页池和非页面缓冲池跟内核内存有关,暂不讨论),做软件工程师多年,大家真的懂任务管理器中这些内存相关的列吗?譬如什么工作集,专用工作集等等,另外像其它的一些常用工具,譬如ProcessExplorer里面可能又是叫Working Set,Private Bytes。

另外像SetProcessWorkingSet,EmptyWorkingSet这些函数真的是洪水猛兽,完全不能使用吗?本文将简单讨论下这些问题,另外简单介绍下VMMap工具的使用。

名词解释

先进行一下名词解释,其实这个地方容易搞混的一个原因也是不同的工具的描述不一样,导致有些混乱,因此这里先把这些概念统一下,然后再进行解释(WS:Working Set的简称,none:表示无对应的显示选项)。

Win7任务管理器中名称 Process Explorer中名称 VMMap中的名称
工作设置(内存) Working Set Total WS
内存(专用工作集) WS Private Private WS
提交大小 Private Bytes Private(or Private Bytes)
内存(共享工作集)* WS Shareable Shareable WS
none WS Shared Shared WS
none Virtrual Size Size
none none Committed

*Win10上面有共享工作集的展示

工作设置(内存)/Working Set/Total WS: 专用(私有)工作集(当前进程独占)中的物理内存数量与进程正在使用且可以和其他进程共享的物理内存数量的总和,因此可以这么理解,该值就是该进程所占用的总的物理内存,但是这个值是由两部分组成,即"专用工作集"和"共享工作集"(Win10的任务管理器里面可以看到共享工作集)。在深入解析Windows操作系统里面是这样描述的:物理上驻留在内存中的那一部分子集称为工作集(Working Set)。

峰值工作设置(内存): 进程的工作设置(内存)的最值,可以这么理解,因为工作设置(内存)是波动的,这个项专门记录最大的那个值。

内存(专用工作集)/WS Private/ Private WS: 工作集的子集,它专门描述某个进程正在使用且无法与其他进程共享的物理内存值。这个值对于一个进程来说也是最重要的,它代表了一个进程到底独占了多少物理内存。

内存(共享工作集)/ WS Shareable/ Shareable WS: 进程和可以和别的进程共享的物理内存值(注意:是可以共享的,不一定共享了)。比较常见的,譬如,加载系统的一些DLL所占用的物理内存,文件共享内存(文件映射),命名共享内存等等。

WS Shared/ Shared WS: WS Shareable的子集,这部分是表示已经和别的进程共享的物理内存。

提交大小/ Private Bytes/ Private: 给当前进程使用而保留的私有虚拟内存的数量,从名字里面的Private可以看出它是专有的,但是和上面的WS Private的区别在于,WS Private是纯物理内存,而Private Bytes实际上是虚拟内存的概念,是包含WS Private的,另外一部分是在换页文件(被从物理内存里面换出去了)里面,有些内存,虽然你提交,但是如果一直没有使用,也是在页面文件(换页文件:PageFile)里面。另外,多说一句,如果要查内存泄漏,可以关注这个值。

Virtrual Size/Size: 当前进程使用的所有的虚拟内存空间,包含共享,非共享,物理,页面,甚至为程序保留但还未分配的内存。

Committed: Virtual Size减去为程序保留的内存(未分配)。怎么理解为程序保留的但未分配的内存?就是告诉系统我要一块内存,但暂时还用不上,不过分配的地址得给我,系统就给程序一个不用的地址,但不分配内存,等程序真的要使用时(读写),就从页面或物理内存中分配出来映射到那个地址上。

保留(预定)的内存: 将虚拟内存空间中线性地址0xXXXXXXXX-0xYYYYYYYY标记为预定状态,但是并没有分配实际的内存。这样的好处是我先预定一部分线性地址,以免后面进程空间中没有这么大的地址范围可用(一般来讲只有服务器上面这样用得多)。这样预定后,0xXXXXXXXX-0xYYYYYYYY这块地址就被占用,地址空间也是资源,虽然还没有分配任何内存。

提交的内存: 系统从物理内存或者换页内存分配给进程的那一部分。这部分内存在虚拟内存的线性地址中是连续的,不过在物理内存或者换页内存中,不一定是连续的。提交但未使用的内存一般都在换页内存里面,只有去使用的时候,才会换到物理内存里面,这点要注意。

换页内存: 也属于已经提交的内存,不过因为不常用,可能被系统置换到磁盘上面以节省物理内存,后面如果要使用会发生换页错误(缺页中断),再从磁盘上面置换到物理内存。

缺页中断: 当程序要访问某个地址,系统发现这个地址不在物理内存里,就会产生中断,然后去读取页面文件,把页面文件中与内存相关的数据拷贝到物理内存,然后标记一下这个地址已经在物理内存中了,然后继续让程序运行。

虚拟内存、物理内存和换页内存: (整个概念还是有一些复杂,这里只简单描述一下)虚拟内存一般是指整个进程用到的(虚拟)地址空间,之所以是虚拟的,因为中间被系统内存管理器抽象了一层,说到这里就牵涉到一个进程的虚拟内存空间的问题,win32下面一般应用层的虚拟地址空间是2G,然后从虚拟内存地址到物理内存有一个映射关系,这个映射是由内存管理器来完成的,对应用程序透明。而虚拟内存里面一般分成保留内存(压根就还没分配的,只是占了地址空间的坑),物理内存(正在使用)和换页内存(从物理内存换出去的,或者分配后一直未使用),另外物理内存和换页内存都属于已经提交的内存。

分页池: 由内核或驱动程序代表进程分配的可分页内核内存的数量。可分页内存是可以写入其他存储媒介(例如硬盘)的内存。

非分页缓冲池: 由内核或驱动程序代表进程分配的不可分页的内核内存的数量。不可分页的内存是不能写入其他存储媒介的内存。内核在处理低优先级的中断时,仍可以发生(处理)高优先级的中断,反过来则不行。缺页过程也是一个中断过程(缺页中断),那么就遇到了一个问题,即缺页中断和其他中断的优先级的问题。如果在高于缺页中断的中断优先级上再发生缺页中断,内核就会崩溃。所以在DISPATCH_LEVEL级别以上,绝对不能使用分页内存,一旦使用分页内存,就有发生缺页中断的可能,如果发生就会导致内核崩溃(蓝屏)。

简单总结下:

1、工作设置(内存),又叫工作集,即在物理内存中的数据的集合且等于专用工作集与共享工作集的和,Working Set = WS Private + WS Sharable。

2、把所有的"工作集"相加后的值会大于任务管理器中提示的物理内存的使用值,因为工作集包含了共享工作集,这部分数据会重复计算。但是如果你只把专用工作集全部加起来又会发现小于任务管理器中提示的物理内存的使用值,因为你完全没有计算共享工作集。

3、通俗的讲工作设置(内存)是程序占用的物理内存(包含与其他程序共享的一部分),内存专用工作集是程序独占的物理内存,提交大小(Private Bytes)是程序独占的内存(包含物理内存和换页内存)。

4、Committed = VM Private Committed + VM Shareable Committed(VM:虚拟内存)

5、Committed = Working Set + Page File Committed

6、Private Bytes = WS Private + Page File Private

介绍一个测试Windows极限的工具TestLimit,这个玩意功能挺多的,可以探测Windows系统物理内存,虚拟内存,分页&非分页内存,进程&线程,句柄,用户对象和GDI资源等的极限,这里用来探测一下内存的极限。以后有空了可以聊聊Windows其它一些系统资源的极限情况。

命令行 含义 参考PID
TestLimit -r 2048 -c 1 Reserve 2G内存 13520
TestLimit -m 2048 –c 1 Commit 1G 内存, 但不访问这些内存 12448
TestLimit –d 2048 –c 1 Commit 1G内存, 而且访问这些内存 13208

*参考了网上的实验。

根据PID进行对照,会发现,不同的情况影响的内存参数并不一样,大家可以自己做做这个实验体会下,对于系统内存机制会有更进一步的了解。

内存优化的概念

1、进行内存优化时,我们主要关注的指标有,工作设置(内存)/Working Set,内存(专用工作集)/WS Private,Private Bytes等几个,具体实践时要针对性优化。譬如要优化私有物理内存的使用,那么主要关注当前进程模块分配内存的特征和大小,找到主要的矛盾点。如果要优化共享内存的使用,除了关注命名共享内存的大小,文件映射之外,还要排除下进程加载的模块的大小是否有影响。

2、高峰工作集(内存)这个指标一般关注比较小,也较少针对性的优化,主要是评估下内存使用是否平滑。在一些内存资源非常紧张的系统,要注意这个地方,防止内存高峰时,整个系统响应速度雪崩式下降。

3、在进行内存优化时,首先要用相关工具进行内存分配的聚类和分析,然后再制订优化的方案和计划,首先要分清是内存使用不合理导致的问题,还是某些算法使用内存时可以进行技术上优化,不同的情况消耗的时间是完全不一样的。

4、补充说明下经常被视为"洪水猛兽"的"刷内存",也就是调用SetProcessWorkingSet和EmptyWorkingSet(实际上是和使用特殊参数调用SetProcessWorkingSet类似)把强制系统把某个进程的部分物理内存置换到换页内存里面,其实Committed是不会变化的,但是短时间内Working Set会有明显的变化,为什么说是短时间内,因为虽然某些物理内存页临时置换到换页内存了,但是因为进程马上可能就用到的,又会立即被换出来,因此做完这个动作之后,关注下该进程的Page Fault值,会发现有明显的增量,反而可能影响系统性能。这两点(性能反而下降,假内存优化)也是这种方法被长期诟病的一些原因。不过,任何事情都有两面性,霸蛮点说,系统为什么提供这种API?完全没用的话,系统为什么不干掉。其实系统自己也在使用,虚拟内存管理器也会通过这个方法释放更多的物理内存给应用程序使用。当然,无节操的调用当然不行,什么一秒调用一次这种奇葩的操作,这样肯定会影响性能,那一般应该怎样使用呢?这里总结了几点,大家可以根据情况参考下:

(1) 维持专用工作集(内存)和提交大小(Private Bytes)在一个合适的比例,不停的刷,物理内存600 KB,虚拟内存50M,这一看就不合理,一般来讲(个人经验),维持在1 : 2左右比较合理。实践中建议根据进程稳定之后的内存来设置这个值。

(2) 建议在程序暂时不被使用的时候(例如最小化,闲时),或者刚刚完成了一件很消耗物理内存的动作之后,进行一次合理的设置。

(3) 启动2~5分钟之后进行一次设置,这个跟启动时内存消耗的特点有关系,很多对象的生命周期都是和进程一样长,在初始化时,使用了很多STL,ATL或者自定义的对象,消耗了很多内存,但是这些对象可能就启动时用到了,后面大部分情况可能都用不到,但是它们的生命周期又很长,因此可以在启动一段时间之后,把这部分内存置换出去。另外,不建议在进程的生命周期中定时的去刷这个内存,即使要刷,也要降低刷的频率,甚至不刷。

VMMap常用功能举例

(略,后面有空再补充,这个工具本身就很简单)。

参考文档

1、https://www.cnblogs.com/walfud/articles/3256233.html Windows 任务管理器中的几个内存概念

2、https://www.zhihu.com/question/19858114 Windows 7 里进程管理器里面的各列是什么含义?主要是和内存有关的内存-专用工作集,内存-工作集,内存-提交大小,这些之间有什么区别?

3、https://www.cnblogs.com/awpatp/archive/2012/09/17/2688315.html Windows内存的一些知识点

4、http://shashanzhao.com/archives/832.html windows任务管理器中的工作设置内存,内存专用工作集,提交大小详解

5、https://superuser.com/questions/185318/process-explorer-not-showing-the-biggest-user-of-my-ram Process Explorer not showing the biggest user of my RAM VMMAP显示和process explorer不一样?

6、http://www.cnblogs.com/georgepei/archive/2012/03/07/2383548.html 内存详解

7、http://www.cnblogs.com/georgepei/archive/2012/03/07/2383445.html 你真的懂任务管理器中有关内存的参数Private(提交大小)和working set(工作设置)吗?

8、http://blog.csdn.net/lantianjialiang/article/details/5620647 process explorer中的visual size vs working set; private bytes vs WS private

9、http://www.cnblogs.com/awpatp/archive/2010/01/26/1656651.html Task Manager跟Performance Monitor的区别(Working set和Private bytes)

10、https://social.microsoft.com/Forums/zh-CN/155e9b0e-8dd9-449a-960c-ce585850a049?prof=required 为什么任务管理器里面所有进程占用的内存加起来远远小于内存使用量?

11、https://blogs.technet.microsoft.com/markrussinovich/2008/11/17/pushing-the-limits-of-windows-virtual-memory/ Pushing the Limits of Windows: Virtual Memory

猜你喜欢

转载自blog.csdn.net/magictong/article/details/78998944