我正在使用VMMap来分析混合模式(托管和非托管)应用程序中的虚拟/进程地址空间利用率.我了解Windows VMM和虚拟内存API的工作原理,我也了解堆内存API的工作原理.我已经看过我正在使用的CRT实现(不是非常详细)和(我想我 - 这可能是我的堕落)了解它如何使用前面提到的Win32 API.
我想了解这个"私人数据"统计数据给我看的内容.我的应用程序不直接调用任何Win32内存API函数,它只在本机C++中使用"malloc/new",在C#中使用"new"(深入使用Win32内存管理API).
VMMap给出的"私有数据"的定义是:
私有内存是由VirtualAlloc分配的内存,不是由堆管理器或.NET运行时子分配的.它不能与其他进程共享,根据系统提交限制收费,并且通常包含应用程序数据.
所以我想这个定义让我问,好吧,那么谁在调用VirtualAlloc呢?它是堆管理器还是.Net运行时?
我可以得到一些已提交的私有数据的地址,并使用WinDbg找出....嗯......事实证明,微软在他们的智慧中扼杀了ntdll公共符号,所以WinDbg不能很好地工作 - 我如果需要,可以提供更多关于此的详细信息,但基本上命令如!address -summary由于缺少符号而不再起作用.
提出这个问题的另一种方法可能是:我可以编写哪些C++或C#代码会导致此私有数据统计数据增加或减少?或者这一切都是由操作系统,C++运行时或.Net运行时管理的,因此受到它的突发奇想?
我可以从VMMap的性质(其他内存类型是唯一的其他内容)推断出这个"私有数据",因此不能是以下任何类型的地址空间:
(我找不到一个在线帮助文件,它定义了VMMap认为上述所有类型的内容,但是这里有一个下载帮助文件的链接:https://technet.microsoft.com/en-us/library/dd535533.aspx)
我注意到在我的应用程序中,私有数据的TOTAL(保留和提交)大小在我的应用程序生命周期内保持相当稳定,尽管堆/管理堆/堆栈大小按预期更改.我还注意到私有数据使用的总量约为250Mb,实际上只提交了~33Mb.请注意我的测量方法相当简陋,所以我的每次测量之间的值可能会发生变化而我只是没有看到它(如果我知道这是测量的,我可以使用DebugDiag来抓取过程的转储相关的柜台达到一定的门槛,鸡肉和鸡蛋).
我目前的推测理论是,这个空间被保留用于增长原生(或管理我认为?)堆积,因为它们达到了他们的能力,但我没有任何证据证明这一点.所以它仍然坚定地投机于投机.
在互联网上搜索有关这方面的详细信息可能很痛苦,有许多帖子/文章/博客会混淆事物,使用自我引用定义(Performance Monitor的工作集定义的第一句就是一个很好的例子),不完整或完全错误.许多地方模糊定义或使用不一致的术语(请注意,VMMaps定义字段私有数据,继续将其称为私有内存,可能有点肛门投诉,但含糊不清).
现在我批评互联网的其余部分是为了让事情变得混乱和不正确...如果上面有什么内容没有意义,或者你可以向我展示相反的文档,或者你需要一个更明确的定义,让我知道,我也将自己列入违法者名单!我认为上半部试图向某人解释内存问题,在网上,确保我们都在谈论同样的事情.
最后这个问题:VMMap如何知道给定的内存区域是Thread Stack,具体来说呢?建议我可能永远找不到答案:/
UPDATE/EDIT:我发现通过打开gflags用户堆栈跟踪(gflags -i myapp.exe + ust),你可以增加私有数据的大小,我会假设这是回溯数据库,但是甚至没有gflags ,我仍在努力解决私人数据问题.
我想弄清楚VMMAP进程是如何运作的.
在使用dtrace运行此可执行文件后,似乎方法proc_regionfilename提取虚拟内存中每个部分的地址空间.
所以,我深入挖掘,并在文件
libsyscall/wrappers/libproc/libproc.c 下的xnu中找到它的实现.
在函数体中,我看到主调用是proc_pidinfo:
retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, ®info, sizeof(struct proc_regionwithpathinfo));
Run Code Online (Sandbox Code Playgroud)
而proc_pidinfo又调用了__proc_info符号:
int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
Run Code Online (Sandbox Code Playgroud)
但是,这个符号在代码中找不到,我想知道它是如何在预编译,编译,链接或实时创建的.
任何想法我在哪里可以找到它,或者它是如何创建的(我还没有尝试编译内核).
谢谢
我有一个C#应用程序,其内存使用时间增加.我定期进行用户模式转储,加载sos后,运行!EEHeap -gc来监控托管堆大小.在windbg/sos中我看到它开始~14MB并且长到160MB,然后缩减到15MB,但应用程序"Private Bytes"从未显着下降.我已经确定了可以控制"私有字节"增加的活动,因此我可以控制内存增长何时发生.
我尝试运行Vmmap.exe并注意到它报告了~360MB的托管堆,快速转储并使用windbg/sos/eeheap -gc我只看到15MB.
为什么我会看到这样不同的价值观?托管堆真的是vmmap.exe报告的吗?
如何在windbg中检查托管堆的这个区域?