C#和VB:System.Func需要多少内存?

9

System.Func占用多少内存?

如果System.Func只有1行代码和1000行代码,是否有区别?


2
System.Func 只是已编译代码的指针。为了大致了解,请看一下添加代码前后 DLL 的大小。 :) - Jeff Meatball Yang
4个回答

18

Func<>是一个委托类型,在x86 jitter中,它的实例占用32字节的存储空间:

  • 8字节用于对象头
  • 4字节用于Delegate._methodBase字段
  • 4字节用于Delegate._methodPtr字段
  • 4字节用于Delegate._methodPtrAux字段
  • 4字节用于Delegate._target字段
  • 4字节用于MulticastDelegate._invocationCount字段
  • 4字节用于MulticastDelegate._invocationList字段

目标方法的大小不相关,委托对象仅存储方法的地址。


invocationCount(和列表)是指它被调用的次数还是指向它的东西的数量?(或其他什么?) - Hogan
1
委托指向多少个目标。它被事件使用。 - Hans Passant
哦,我猜那个改变了.. 我记得有一个 prev 字段会先执行。 - Hogan

8
这个问题有很多层次的答案,我担心您无法获得真正100%准确的答案,但是让我试着回答一下。这里有两个不同的内存块需要关注:
1. 用于保存代码的内存 2. 由代码分配的内存
第一个内存块由JIT编译器分配,它与方法中的代码量肯定有关。但是,如果您决定将该方法分散到多个方法中(应该这样做,一个方法不应该超过1000行,甚至不应该超过50行),那么您也将内存分散到这些方法中。实际上,每个方法可能会产生一定的开销,所以从这个角度来看,如果您使用了更多的方法而不仅仅是一个大方法,那么为JIT编译的代码使用的内存可能会增加,但这并不重要。将其分割开来。认真对待。
第二个内存块是代码执行时分配的任意内存。当然,这完全取决于代码的操作,因此无法仅根据代码行数判断一个方法比另一个方法更好。 一个千行的方法可能不会分配多少内存,而一个单行的方法可能会分配很多内存。除非检查实际的代码,否则无法确定。
此外,在发布模式下(在调试器之外运行),垃圾回收器非常激进,因此在方法顶部声明一个变量、填充数据结构,然后再此后的代码中不再使用,GC可能会收回该变量,因为它可以“看到”变量不再使用,所以可以安全地收集其中的任何内容。
但是,在调试期间,该变量的生命周期被人工延长到作用域/方法结束,这样,如果您在代码段的某个部分停止程序并且该变量不再使用,则仍然可以检查其内容。
因此,总之:
1. 较长的方法可能需要比较短的方法更多的JIT编译内存来保存,但除非您可以实际删除代码,而不仅仅是移动它并将其分割开,否则这并不重要。 编写短方法。 2. 方法分配的内存与行数无关,而与这些行的内容有关。
至于System.Func ,那只是指向一个小对象的指针。该对象的大小将取决于func/method引用的参数数量(如果我记得正确),但除此之外,它与方法、代码或内存分配等无关。
正如@Marc所指出的,.NET中的委托支持多路广播。这使用一系列对象解决,因此所使用的内存也取决于该链中的元素数量。
不要担心使用委托。它们在CPU和内存方面都非常便宜。

3
System.Func仅仅是一个委托,简单地说它保存了一系列指向函数的指针,因此,System.Func占用的内存与其所分配的函数委托数量成正比,而与其所指向的函数实际大小无关。
另一方面,函数本身的内存需求取决于代码行数和代码实际执行情况。你应该关注后者,即实现函数的内存分配需求和算法效率。

0

我不知道这有多大帮助,但使用它我们可以了解一个进程的内存使用情况。

int memory;
Process[] application;
application = Process.GetProcessesByName("MyApplication.exe");
applicationMemory = application[0].PrivateMemorySize;
Console.WriteLine("Memory used: {0}.", applicationMemory);

我认为代码行数的多少并没有什么区别。你可以使用分析器来解决这个问题。下载你的分析器工具包,将你的应用程序附加上去,然后你就可以看到代码的内存使用情况,我想这会对你有所帮助……


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接