首页 文章

什么是专用字节,虚拟字节,工作集?

提问于
浏览
428

我试图使用perfmon Windows实用程序来调试进程中的内存泄漏 .

这就是perfmon解释这些术语的方式:

Working Set 是此进程的工作集的当前大小(以字节为单位) . 工作集是过程中线程最近触及的一组内存页面 . 如果计算机中的可用内存超过阈值,则即使不使用页面,页面也会保留在进程的工作集中 . 当可用内存低于阈值时,将从工作集中剪裁页面 . 如果需要它们,它们将在离开主存储器之前被软故障返回工作集 .

Virtual Bytes 是进程正在使用的虚拟地址空间的当前大小(以字节为单位) . 使用虚拟地址空间不一定意味着相应地使用磁盘或主存储器页面 . 虚拟空间是有限的,并且该过程可以限制其加载库的能力 .

Private Bytes 是此进程已分配的内存的当前大小(以字节为单位),无法与其他进程共享 .

这些是我的问题:

是否应该测量私有字节,以确定进程是否有任何泄漏,因为它不涉及任何共享库,如果发生任何泄漏,将来自进程本身?

该进程消耗的总内存是多少?它是虚拟字节还是虚拟字节和工作集的总和?

私有字节,工作集和虚拟字节之间是否有任何关系?

还有其他工具可以更好地了解内存使用情况吗?

4 回答

  • 446

    对这个问题的简短回答是 none of these values are a reliable indicator of how much memory an executable is actually using, and none of them are really appropriate for debugging a memory leak.

    Private Bytes 指的是进程可执行文件要求的内存量 - 不一定是它实际使用的量 . 它们是"private"因为它们(通常)排除了内存映射文件(即共享DLL) . 但是 - 这里's the catch - they don' t必然会排除这些文件分配的内存 . 没有办法判断私有字节的更改是由于可执行文件本身还是由于链接库 . 专用字节也是 not 专用的物理内存;它们可以被分页到磁盘或备用页面列表(即不再使用,但也没有被分页) .

    Working Set 指的是进程使用的总 physical 内存(RAM) . 但是,与私有字节不同,这还包括内存映射文件和各种其他资源,因此它近年来一直是无穷无尽的混乱的根源 . 工作集中的内存是"physical",因为它可以在没有页面错误的情况下进行寻址;但是,备用页面列表在物理上仍然在内存中,但未在工作集中报告,这就是为什么在最小化应用程序时可能会看到"Mem Usage"突然下降的原因 .

    Virtual Bytes 是整个过程占用的总数 virtual address space . 这就像工作集一样,它包含内存映射文件(共享DLL),但它还包括备用列表中的数据和已经被分页的数据,并且位于磁盘上的页面文件中 . 在高负载下系统上的每个进程使用的总虚拟字节将比机器实际拥有的内存大得多 .

    所以关系是:

    • Private Bytes是您的应用实际分配的内容,但包含页面文件用法;

    • Working Set是非分页私有字节加内存映射文件;

    • 虚拟字节是工作集加分页的专用字节和备用列表 .

    有's another problem here; just as shared libraries can allocate memory inside your application module, leading to potential false positives reported in your app'的私有字节,您的应用程序也可能最终在共享模块内分配内存,导致错误否定 . 这意味着您的应用程序实际上可能存在内存泄漏,而这种内存泄漏根本不会出现在Private Bytes中 . 不太可能,但可能 .

    私有字节是您的可执行文件使用的内存量的合理 approximation ,可用于帮助缩小内存泄漏的潜在候选列表;如果你看到这个数字不断增长并且不断增长,你会想要检查这个过程是否有泄漏 . 但是,这不能证明存在或没有泄漏 .

    在Windows中检测/纠正内存泄漏的最有效工具之一实际上是Visual Studio(链接转到使用VS进行内存泄漏的页面,而不是产品页面) . Rational Purify是另一种可能性 . 微软在这个问题上也有一个更普遍的best practices document . 有此previous question中列出的更多工具 .

    我希望这清除了一些事情!追踪内存泄漏是调试中最困难的事情之一 . 祝好运 .

  • 5

    您不应该尝试使用perfmon,任务管理器或任何类似的工具来确定内存泄漏 . 它们有助于识别趋势,但不是很多 . 他们以绝对术语报告的数字过于模糊和聚合,无法用于特定任务,如内存泄漏检测 .

    之前对这个问题的回答很好地解释了各种类型的内容 .

    您询问工具建议:我建议使用Memory Validator . 能够监控进行数十亿内存分配的应用程序 .

    http://www.softwareverify.com/cpp/memory/index.html

    免责声明:我设计了Memory Validator .

  • 7

    perfmon计数器的定义从一开始就被打破了,由于某种原因似乎太难以纠正 .

    MSDN上的视频“Mysteries of Memory Management Revealed”提供了对Windows内存管理的概述:它涵盖了跟踪内存泄漏所需的更多主题(例如工作集管理),但在相关主题中提供了足够的详细信息 .


    为了向您提供有关perfmon计数器描述的问题的提示,以下是有关MSDN上“Private Bytes Performance Counter -- Beware!”的专用字节的内幕故事:

    问:私有字节何时不是私有字节?答:当它不是居民时 . Private Bytes计数器报告进程的提交费用 . 也就是说,交换文件中分配的空间量,用于在交换出来时保存私有内存的内容 . 注意:我避免使用“保留”一词,因为可能会混淆未提交的保留状态中的虚拟内存 .


    来自MSDN上的“Performance Planning”:

    3.3专用字节3.3.1描述专用内存,定义为为进程分配的内存,不能被其他进程共享 . 当多台此类进程在计算机上执行时,此内存比共享内存更昂贵 . (传统)非托管dll中的私有内存通常由C静态构成,并且是dll总工作集的5% .

  • 9

    这里有一个有趣的讨论:http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/我对这个主题的理解是释放小分配不会反映在私有字节或工作集中 .

    长话短说:

    如果我打电话

    p=malloc(1000);
    free(p);
    

    那么私有字节只反映分配,而不是反释 .

    如果我打电话

    p=malloc(>512k);
    free(p);
    

    那么私有字节正确地反映了分配和释放 .

相关问题