Home All Groups Group Topic Archive Search About

Calculate memory consumed.

Author
25 Jul 2006 2:28 PM
Praveen
Hello all,
In my application I have a datacache class which stores xml objects which
are frequently used. Caching objects can improve performance but they come
at the cost of memory and in my case since the number of xml objects can be
huge I wanted to put an upper limit to the memory allocated to the Cache
class.

Is there a way in dotnet that I can find out the total memory consumed by a
class. similar to Environment.WorkingSet which gives the memory consumed for
the entire application.

Thanks in advance..
Praveen.

Author
25 Jul 2006 3:03 PM
Barry Kelly
"Praveen" <praveen@newsgroup.nospam> wrote:

> In my application I have a datacache class which stores xml objects which
> are frequently used. Caching objects can improve performance but they come
> at the cost of memory and in my case since the number of xml objects can be
> huge I wanted to put an upper limit to the memory allocated to the Cache
> class.
>
> Is there a way in dotnet that I can find out the total memory consumed by a
> class. similar to Environment.WorkingSet which gives the memory consumed for
> the entire application.

For a single type? Iterate through each field and sum up the values: use
Marshal.SizeOf for value types and IntPtr.Size for reference types. For
instances, you'll have to work a lot harder, especially if you want the
total size of the graph being referred to. You'll need to guard against
recursion of references and avoid double-counting value types, which
will be boxed when you try to use reflection to examine their fields.
You'll need permissions to look inside the private members too.

You could also consider wrapping your cache objects in a WeakReference
so the GC can collect occasionally. Truism: the trickiest part about
caching is getting a good expiration policy right, otherwise it's just a
memory leak.

-- Barry

Author
26 Jul 2006 10:18 AM
Walter Wang [MSFT]
Thanks Barry for your informative input.

Hi Praveen,

Thank you for your post.

As Barry pointed out, a good expiration policy of is key to your caching
system.

To get memory size of a single type, we can use Type.TypeHandle to get the
basic instance size of this type. You can use following code to test:

=====
using System;

class SimpleClass
{
    private byte b1 = 1;                // 1 byte
    private byte b2 = 2;                // 1 byte
    private byte b3 = 3;                // 1 byte
    private byte b4 = 4;                // 1 byte
    private char c1 = 'A';              // 2 bytes
    private char c2 = 'B';              // 2 bytes
    private short s1 = 11;              // 2 bytes
    private short s2 = 12;              // 2 bytes
    private int i1 = 21;                // 4 bytes
    private long l1 = 31;               // 8 bytes
    private string str = "MyString"; // 4 bytes (only OBJECTREF)

    //Total instance variable size = 28 bytes

    static void Main()
    {
        SimpleClass simpleObj = new SimpleClass();
        int basicInstanceSize = GetBasicInstanceSize(simpleObj.GetType());
        Console.Write(basicInstanceSize);
    }


    /// <summary>
    /// Gets the size of instances of the given type. It is the sum of:
    ///   - a fixed object overhead (8 bytes)
    ///   - the sizes of all the instance fields (note: may include padding)
    /// For more information see:
    ///   -
http://msdn.microsoft.com/msdnmag/issues/05/05/JITCompiler/default.aspx
    ///   -
http://msdn.microsoft.com/msdnmag/issues/05/05/JITCompiler/default.aspx?fig=
true#fig9
    /// </summary>
    /// <param name="type">A type.</param>
    /// <returns>Size in bytes of instances of the given type.</returns>
    private static int GetBasicInstanceSize(Type type)
    {
        // Read the first 8 bytes (=2 ints) of the MethodTable. The basic
instance size is the second int.
        IntPtr methodTableIntPtr = IntPtr.Zero;
        try
        {
            methodTableIntPtr = type.TypeHandle.Value;
            int[] methodTableData = new int[2];
            System.Runtime.InteropServices.Marshal.Copy(methodTableIntPtr,
methodTableData, 0, 2);
            int basicInstanceSize = methodTableData[1];
            return basicInstanceSize;
        }
        finally
        {
            if (methodTableIntPtr != IntPtr.Zero)

System.Runtime.InteropServices.Marshal.Release(methodTableIntPtr);
        }
    }
}
=====

Hope this helps. Please feel free to post here if anything is unclear.

Sincerely,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
26 Jul 2006 11:31 AM
Barry Kelly
waw***@online.microsoft.com (Walter Wang [MSFT]) wrote:

> To get memory size of a single type, we can use Type.TypeHandle to get the
> basic instance size of this type. You can use following code to test:

>         // Read the first 8 bytes (=2 ints) of the MethodTable. The basic
> instance size is the second int.

This low-level hacking might not work in other implementations of the
CLI, and could change in future versions. There's nothing in the CLI
that mandates the existence or layout of a method table, to my
knowledge. I wouldn't recommend this method.

The only mention of a method table I can find in the CLI is in reference
to the contents of the PE file metadata.

(I am aware of method tables from spelunking with WinDbg & SOS, and the
SSCLI sources.)

-- Barry

Author
26 Jul 2006 12:31 PM
Walter Wang [MSFT]
Hi Barry,

Thank you. I should have pointed out that this is undocumented and may
change in future version.

Also this approach can only report basic instance size of a type, not
necessary a runtime instance size.

Another approach would be using .NET Profiler API to get object size.

#Inspect and Optimize Your Program's Memory Usage with the .NET Profiler API
http://msdn.microsoft.com/msdnmag/issues/03/01/netprofilerapi/


Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

AddThis Social Bookmark Button