是否有一种方法可以获取分配的总数(注意-分配数量,而不是分配的字节数?它可以是当前线程,也可以是全局线程,以较容易的一个为准。
[我想检查一个特定函数分配了多少个对象,虽然我知道调试-> Performance Profiler(Alt + F2),但我希望能够从程序内部以编程方式进行操作。
// pseudocode
int GetTotalAllocations() {
...;
}
class Foo {
string bar;
string baz;
}
public static void Main() {
int allocationsBefore = GetTotalAllocations();
PauseGarbageCollector(); // do I need this? I don't want the GC to run during the function and skew the number of allocations
// Some code that makes allocations.
var foo = new Foo() { bar = "bar", baz = "baz" };
ResumeGarbageCollector();
int allocationsAfter = GetTotalAllocations();
Console.WriteLine(allocationsAfter - allocationsBefore); // Should print 3 allocations - one for Foo, and 2 for its fields.
}
此外,我是否需要暂停垃圾收集以获取准确的数据,我可以这样做吗?
我需要使用CLR分析API来实现吗?
[您需要使用一些kernel32函数,但是有可能!! :)我没有编写完整的代码,但是希望您能感觉应该怎么做。
首先,您需要使用功能进行所有处理:Process.GetProcesses
link那么您需要从中创建快照CreateToolhelp32Snapshot
,因为此快照不需要“ GC暂停”,并且需要创建循环以枚举所有内存块之后。使用Heap32ListFirst
和Heap32First
初始化循环功能,然后可以调用Heap32Next
直到成功。
并且当它在您的代码中这样声明时,您可以调用kerner32函数:
[DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
static extern IntPtr CreateToolhelp32Snapshot([In]UInt32 dwFlags, [In]UInt32 th32ProcessID);
这里是c ++示例,但是您可以在CSharp函数声明之后执行相同的操作:Traversing the Heap List
我知道这并不容易,但是没有简单的方法。顺便说一下,如果您在循环内调用Toolhelp32ReadProcessMemory
,则可以检索许多有用的其他信息。
而且我发现pinvoke.net可能对您有帮助pinvoke.net
https://www.pinvoke.net/default.aspx/kernel32.createtoolhelp32snapshothttps://www.pinvoke.net/default.aspx/kernel32.Heap32ListFirst
至少在当前情况下,您要问的是不可能的,让我们看看为什么。
有没有办法获得分配总数
是的,有可能。但是我假设您认为每次使用new
运算符创建的对象都会在堆上发生分配。那不是真的堆是按段分配的。在填满最后一个分配的段之前,GC可能会分配几个new
操作员调用,然后GC决定分配一个新的。
此图说明了这种情况:堆中有几个段,但是它们被不同的对象填充。
因此有一种方法可以获取分配的段数,但是它们不对应于对象数,它们的大小也可以不同;第一个段可以为100个字节,另一个段可以为800个字节。
我要检查特定功能分配了多少个对象
您可以在给定的时刻获得多少个对象。无法将信息缩小到特定功能。您可以假设,如果您两次计算堆中有多少个对象,一次是在函数调用之前,一次是在函数调用之后,那么您将能够从另一个中减去一个值并获得差值。
这里的问题是,可以在应用程序中的这两次测量之间分配数百万个对象,因此您的函数分配将显得微不足道,无法获得真实的画面并将函数分配与所有其他对象区分开。
我编写了代码来说明这些方法,您可以找到它here。我使用EnumerateObjectAddresses
获取堆上对象的地址,并使用ETW的TraceEvenSession.Source.Clr.GCAllocationTick
获取有关段分配的事件。