Calculate memory consumed.

P

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.
 
B

Barry Kelly

Praveen said:
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
 
W

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 ([email protected], 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.
 
B

Barry Kelly

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
 
W

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 ([email protected], 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top