简体   繁体   中英

What is the easiest way to find out how much memory an object uses in .NET?

What is the easiest way to find out how much memory an object uses in .NET?

Preferably without having to resort to a third party tool. Marshal.SizeOf or the sizeof operator look useful but only work with a restricted range of types.

Some related posts:

Asked and answered here: Determine how much memory a class uses?

The quick summary is that if you don't want to use a tool, you need to use the .NET Profiling API

The Profiling API is amazingly powerful, but I don't think it would qualify as "easy" by any stretch of the imagination, so I would strongly recommend using a memory profiling tool - there are some free ones that are OK, and some not-too-expensive commercial ones ( JetBrains dotTrace in particular) that are really good.

Because of .NET's garbage-collected nature, it's somewhat difficult to measure how much memory is really being used. If you want to measure the size of a class instance, for example, does it include the memory used by instances that your instance points to?

If the answer is no , add up the size of all of the fields: Using reflection, iterate through all members of the class; use Marshal.Sizeof(member.Type) for anything that typeof(ValueType).IsAssignableFrom(member.Type) - this measures primitive types and structs, all of which reside in the class's instance allocation. Every reference type (anything that isn't assignable to a valuetype) will take IntPtr.Size. There are a disgusting number of exceptions to this, but it might work for you.

If the answer is yes , you have a serious problem. Multiple things can reference a single instance, so if 'a' and 'b' both point to 'c', then RecursiveSizeOf(a) + RecursiveSizeOf(b) would be larger than SimpleSizeOf(a) + SimpleSizeOf(b) + SimpleSizeOf(c) .

Even worse, measuring recursively can lead you down circular references, or lead you to objects you don't intend to measure - if a class is referencing a mutex, for example, that mutex may point to the thread that owns it. That thread may point to all of its local variables, which point to some C# framework structures... you may end up measuring your entire program.

It might help to understand that a garbage-collected language like C# is somewhat "fuzzy" (from a completely non-technical sense) in the way it draws distinctions between objects and units of memory. This is a lot of what Marshal mitigates - marshaling rules ensure that the struct you're marshaling (or measuring) has a well-defined memory layout, and therefore a well-defined size. In which case, you should be using well-defined, marshalable structs if you intend on using Marhsal.SizeOf().

Another option is serialization. This won't tell you specifically how much memory is in use, but it will give you a relative idea of the size of the object. But again, in order to serialize things, they have to have a well-defined layout (and therefore a well-defined size) - you accomplish by making the class appropriately serializable.

I can post implementation examples if any of the above options appeal to you.

you could also do something like this:

int startMem = GC.GetTotalMemory(true);
YourClass c = new YourClass();
int endMem = GC.GetTotalMemory(true);
int usedMeme = endMem - startMem;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM