Determining memory usage of objects in .NET.

Partly out of curiosity - we want to know what's going on in our application, and partly because we need to find some potential problems in our code, I like to keep track of some common values ​​during the execution of our web applications. This includes in particular the allocated memory of certain object graphs.

Our applications store some data permanently in memory to ensure reliable accessibility. This can add up to several GB of memory, while other applications that do nearly the same stuff only allocate one or two.

Due to the required performance, we are unable to attach memory profilers at runtime. Therefore, it would be a good idea to parse the object graph at runtime to print out which pieces of data are that large in some cases and which are not that large. This will help us to understand much better what is happening with the data and potentially optimize the behavior of our applications.

Object graph means starting from a certain object, measuring its size in memory, recursively following all referenced objects, through all properties, fields, lists with all their elements, etc. and adding their appropriate size until we get information about how much memory is being used by this object and all related objects.

In fact, the question I would like to answer is: When I just released the last reference to this binding object, how much GC would be able to free up when clearing this graph of the object the next time I run it?

+3


source to share


2 answers


If you are not using a profiler, this is a difficult task.

The issue of measuring the size of a graphical object has been raised on SO several times, for example:

Ways to determine the size of a complex object in .NET?

How do I get the size of an object in memory?

Each question got a bunch of answers (feel free to read them), but to be honest, they all suck more or less. You have to admit that there is no reliable way to get this information because it is an implementation detail.

But let's assume that what you really need is not an exact measurement, but some numbers in the chalet to know where the "big boy objects" are.

  • Serialize graph of objects

A simple approach I can think of is serializing your objects using binary formatting to a memory stream and checking the size on it.

  • Use dump files

Another approach would be to create dump files of your application and use them for memory analysis. Visual Studio 2013 introduces a new memory analyzer to help you understand .NET memory usage for your applications from .dmp files built on production machines.



It also shows the size for all objects:

enter image description here

There is an introduction to this in two parts:

Part 1: http://blogs.msdn.com/b/visualstudioalm/archive/2013/06/20/using-visual-studio-2013-to-diagnose-net-memory-issues-in-production.aspx

Part 2: http://blogs.msdn.com/b/visualstudioalm/archive/2013/10/16/net-memory-analysis-enhancements-in-visual-studio-2013.aspx

  • Use Microsoft.Diagnostics.Runtime "CLR MD"

CLR MD is a C # API used to build diagnostic tools. It gives you the power and flexibility to extend the SOS and PSSCOR debugger capabilities in a simple, fast C # API.

The github documentation has an example about a non-linear walking heap that is used to calculate the size of an object. It works the same way as! Objsize in SOS so this command takes an object as a (parameter and counts the number of objects it stores, as well as reports (the total size of all objects that this object stores.

https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/docs/WalkingTheHeap.md

+3


source


It's not clear if this suits your requirements, but the SOS extension for Windbg provides a command !objsize

to determine the recursive size of an object, including all objects that are referenced. You can either connect to a running process or take a memory dump (for example with procdump

) and then connect to the dump file to perform offline analysis. However, the output from !objdump

will only answer your last question if the sub-objects are only reachable from your original object (any other references will, of course, prevent the collection of the sub-object tree even if your original object becomes unreachable).



The reason this is so complex out of the process itself is partly because the runtime necessarily hides a lot of detail about the in-memory views. Some of these can be overcome with unsafe code, however it is still non-trivial, so using something like SOS in Windbg that "knows" the internals of the CLR makes the process much easier, with the obvious limitation that it must be done from "outside" the process, not inside.

+1


source







All Articles