概述
一、开始之前,让我们来了解一下Windows中内存管理的一些知识:
1. 机器的物理内存由两部分组成。一部分为机器的主存RAM,也就是我们内存条的大小;另一部分为虚拟内存,它就在机器的硬盘上,以页文件的形式存在。
2. 每个进程都有自己的虚拟地址空间,对于具有32位寻址能力的机器来说,这个虚拟空间的大小为4GB。现在我们使用的机器就是4GB。
3. 进程的4GB虚拟地址空间又可以分成几个部分,其中进程真正私有的空间少于2GB(这段地址空间被称作“用户方式分区”),其余的2GB多空间都是给操作系统的,且这部分空间被所有的进程共享。(参考Windows核心编程Chapter 13)
4. 为进程“分配内存”,这个概念可以细化:“保留一段地址空间”,“提交一段内存空间”,“将内存空间映射到主存”。在程序中我们通常所访问的地址都必须是进程地址空间中被保留和提交的那段地址空间。
4.1 “保留一段地址空间”:即从进程的4GB地址空间中保留一段地址空间,这个过程通过VirtualAlloc函数完成,并把分配类型参数设置为MEM_RESERVE。这段空间的起始地址必须是系统分配粒度的整数倍,大小必须是系统页面大小的整数倍。
4.2 “提交一段内存空间”:即为进程已保留的地址空间映射机器的物理内存,这里要特别注意,所谓物理内存一般并不是机器的主存,而只是机器的虚拟内存。这个过程同样又VirtualAlloc完成,只是把分配类型参数设置为MEM_COMMIT。这段空间的起始地址和大小都必须是页面大小的整数倍。这样进程的对应被提交的区域就被映射到机器的虚拟内存上。
4.3 “将内存空间映射到主存”:这点很重要,操作系统总是只有在进程提交的页面被访问时才将相应的页面加载到主存中,同时修改进程对应页面的地址空间映射。这时,进程的地址空间中的对应区域才和机器上的主存对应起来。
二、好了,接下来我们看看Process Explorer中关于内存的各个指标分别代表的含义:
Virtual Size:
该指标记录了当前进程申请成功的其虚拟地址空间的总的空间大小,包括DLL/EXE占用的地址和通过VirtualAlloc API Reserve的Memory Space数量。请注意,该指标包括保留的地址空间。
Private Bytes:
该指标记录了进程用户方式分区地址空间中已提交的总的空间大小。无论是直接调用API申请的内存,被Heap Manager申请的内存,或者是CLR 的managed heap,都算在里面。
Working Set:
该指标记录了所有映射到进程虚拟地址空间的机器主存的大小,它不仅仅是用户方式分区部分的映射,而是整个进程地址空间的映射。即它同时包括内核方式分区中映射到机器主存的部分。由4.3可知,在用户方式分区部分只有在进程提交的页面被访问时才将相应的页面加载到主存中。而对于该部分的大小总是系统页面大小的整数倍。
这里有一个问题,随着进程的不断运行,进程被访问的页面将可能不断增加,这是否意味着“Working Set”的大小会不断的累加呢?显然不是。在程序运行过程中影响“Working Set”的因素包括:(1) 机器可用主存的大小 (2) 进程本身“Working Set”的大小范围。当机器的可用主存小于一定值时,系统会释放一些老的最近没有被访问的页面,把这些页面通过交换文件交换到机器的虚拟内存中;当Working Set的大小大于该进程所设置的最大值时,同样会把一些老的页面交换到机器的虚拟内存中。当这些页面下次再被访问时,它们才加载到主存。
由上可知,”Working Set“一定比”Private Bytes“小,因为它只是”Private Bytes“对应的地址空间中被加载到主存的那部分。
“Page Faults”
该指标和”Working Set“密切相关,当进程访问某个页面,而这个页面却不在主存中时,就要发生一次“Page Fault“,即进程访问非”Working Set“中的页面时,发生一次”Page Fault“,同时系统将对应页面加载到主存中。
接下来的三个指标是对”Working Set“的细化:
”WS Private“
该指标记录了进程”Working Set“中被该进程所独享的空间大小。
"WS Shareable"
该指标记录了进程”Working Set“中能与别的进程共享的空间大小
”WS Shared“
该指标记录了进程”Working Set“中已经与别的进程共享的空间大小
”WS Shareable“和”WS Shared“两个指标乍一看令人感到疑惑,因为既然”Working Set“属于”Private Bytes“中的一部分,而”Private Bytes“是进程私有的,为什么会有”WS Shareable“和”WS Shared“这两项呢?
认真一想,其实很容易理解,比如两个进程都需要同一个DLL的支持,所以在进程运行过程中,这个DLL被映射到了两个进程的地址空间中,如果这个DLL的大小为4K,在两个进程中都要提交4K的虚拟地址空间来映射这个DLL。当第一个进程访问了这个DLL时,这个DLL被加载到机器主存中,这时,第二个进程也要访问该DLL,这时,系统就不会再加载一遍该DLL了,因为这个DLL已经在主存中了。当然上面所说的访问仅仅是读取的操作,如果这时候某个进程要修改DLL对应这段地址中的某个单元时,这时,系统必须为第二个进程分配另外的新页面,并把要修改位置对应的页面拷贝的这个新页面,同时,第二个进程中的这个DLL被映射到这个新页面上。
上面的分析中,DLL对应的4K的内存在第一个进程中便是”WS Shareable“。另外,内核方式分区中的所有代码都是被所有进程共享的,只要一个进程访问了这些页面,则在所有的进程的”Working Set“中都能体现。
三、下面我们来讨论一下这些内存指标与进程内存消耗之间的关系
在计算机更新换代不断加速的今天,我们往往很少关注程序对内存的消耗,除非程序的内存消耗超出了我们的忍受范围——大量的泄漏、运行速度下降等。
那么,当我们在测进程的内存使用量时,到底应该使用哪个指标能更好的反应程序的内存消耗呢?由于Windows自带的Task Manager中的”Memory Usage“所对应的指标就是”Working Set“,所以大部分人认为该指标能够很好的反应进程的内存使用量。
在得出结论之前,让我们来分析一下以上的这些指标:
就从”Working Set“开始吧。
”Working Set“:
进程中被加载到机器主存的所有页面大小的和。它可细分为”WS Shareable“和”WS Shared“。进程访问页面不再”Working Set“中时,会发生一次”Page Fault“且同时发生一次主存与虚拟内存之间的数据交换。综上所述,我们可以得出结论:
(a)”Working Set“不是进程内存消耗的全部;
(b)所有进程”Working Set“的和也不等有机器主存总的消耗量,因为存在”Working Shareable“与别的进程共享;
(c)”Working Set“太大会影响机器的运行速度,因为”Working Set“太大会导致机器的可用主存太少,从而导致将进程的老页面释放到虚拟内存,同时,进程”Working Set“中的页面减少好,使进程发生”Page Fault“的频率更高。因为在主存与虚拟内存之间交换数据需要时间,所以机器的运行速度要减慢。
(d)”Working Set“由于数据交换的存在,该指标是动态的,在测量的过程中会不断变化。(变化的最小单位为4K)
所以”Working Set“指标强调的是进程对机器主存的消耗,不是进程内存的全部信息。
"Private Bytes"
该指标包含所有为进程提交的内存,包括机器主存和虚拟内存,可以认为它是进程对物理内存消耗,且该指标相对来说更加稳定。在程序产生内存泄漏时,该值一定是不断上涨的。
综上所述,个人更倾向于使用”Private Bytes“来定量进程的内存消耗和分析进程的内存泄漏。
最后
以上就是可靠水杯为你收集整理的你的进程使用了多少内存?的全部内容,希望文章能够帮你解决你的进程使用了多少内存?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复