Few days ago I came across the following post published by Chris Brumme back in 2004 at http://www.eggheadcafe.com/community/aspnet/2/9568/here-is-what-chris-brumme.aspx:
“We don’t expose the managed size of objects because we want to reserve the ability to change the way we lay these things out. For example, on some systems we might align and pack differently. For this to happen, you need to specify tdAutoLayout for the layout mask of your ValueType or Class. If you specify tdExplicitLayout or tdSequentialLayout, the CLR’s freedom to optimize your layout is constrained.
If you are curious to know how big an object happens to be, there are a variety of ways to discover this. You can look in the debugger. For example, Strike or SOS (son-of-strike) shows you how objects are laid out. Or you could allocate two objects and then use unverifiable operations to subtract the addresses. 99.9% of the time, the two objects will be adjacent. You can also use a managed profiler to get a sense of how much memory is consumed by instances of a particular type.
But we don’t want to provide an API, because then you could form a dependency over this implementation detail.
Some people have confused the System.Runtime.InteropServices.Marshal.SizeOf() service with this API. However, Marshal.SizeOf reveals the size of an object after it has been marshaled. In other words, it yields the size of the object when converted to an unmanaged representation. These sizes will certainly differ if the CLR’s loader has re-ordered small fields so they can be packed together on a tdAutoLayout type.”
FYI: Chris is one of only about 30 Microsoft distinguished engineers in the entire company!
If rough numbers are good enough, and you’re doing this kind of profiling at dev. time, you could also:
1. Get private bytes before the object is allocated:
long size1 = System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;
2. Allocate and initialize your object with data
3. Get private bytes again and measure the difference.