Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# vb: System.Func takes how much memory?

exactly how much memory does a System.Func holds?

Is there any difference if the System.Func is 1 line or 1000 lines?

like image 649
Pacerier Avatar asked Apr 23 '11 17:04

Pacerier


2 Answers

Func<> is a delegate type, an instance takes 32 bytes of storage in the x86 jitter:

  • 8 bytes for the object header
  • 4 bytes for the Delegate._methodBase field
  • 4 bytes for the Delegate._methodPtr field
  • 4 bytes for the Delegate._methodPtrAux field
  • 4 bytes for the Delegate._target field
  • 4 bytes for the MulticastDelegate._invocationCount field
  • 4 bytes for the MulticastDelegate._invocationList field

The target method size is not relevant, the delegate object only stores the address of the method.

like image 173
Hans Passant Avatar answered Sep 27 '22 15:09

Hans Passant


This question has answers on many levels, and I fear you won't get a really 100% accurate one, but here goes.

There are two distinct pieces of memory I want to focus on here:

  1. The memory allocated to hold the code
  2. The memory allocated by the code

The first piece is allocated by the JITter, and this is definitely related to the amount of code in the method. However, if you decide to spread that method out over several methods (which you should, a method should not be a thousand lines long, let alone 50), then you will also spread out the memory over those methods. In fact, there is probably a certain amount of overhead per method so in that light, it might end up using more memory for the JITted code if you use more methods than just one big one, but that's irrelevant. Split it up. Seriously.

The second piece of memory is whatever the code allocates when executing. This is of course wholly dependent on what the code does, so there's no way to say that one method is better than the other judged solely on the number of lines. A 1000 line method might not allocate much whereas a 1-line method might allocate a lot. There's no way to tell, except by examining the actual code.

Additionally, in a release mode build, running outside of the debugger, the garbage collector is very aggressive, so a variable declared at the top of the method, filled with a data structure, and then later on in the method not used any more, GC might reclaim that, since it has a birds-eye view of your code. It can "see" that the variable is no longer in use, so it is safe to just collect whatever is in it.

However, during debugging, that variable has its life artificially prolonged to last until the end of the scope/method, so that if you stop the program somewhere in that portion of the code where the variable is no longer used, you can still inspect its contents.

So, to conclude:

  1. A longer method will likely require more JITted memory to hold than a shorter method, but unless you can actually remove code, as opposed to just shifting it around and splitting it up, it isn't relevant. Write short methods.
  2. The memory allocated by the method is not related to the number of lines, but to the contents of those lines.

Now, as for a System.Func<T...>, that is just a pointer to a small object. The size of that object will depend on the number of the arguments (if I recall correctly) to the func/method it refers to, but otherwise it has no dependence on the size of the method, code or memory-allocation or whatnot.

As @Marc points out, a delegate in .NET is multicast-enabled. This is solved using a chain of objects, so the memory used will also be dependent on the number of elements in that chain.

Do not worry about using delegates. They're fairly cheap, both CPU-wise and memory-wise.

like image 26
Lasse V. Karlsen Avatar answered Sep 27 '22 17:09

Lasse V. Karlsen