RE: XmlSerialization Object Memory Usage
- From: Dave Hiniker - MSFT <DaveHinikerMSFT@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Sun, 15 Oct 2006 21:43:02 -0700
First off, the difference you’re seeing in 2.0 (and likely between your two
machines) is based on what is still live when the GC happens. Since you
don’t use “storage” after calling Collect, it and your created objects are
collectable. You won’t see this in a debug build, because variable lifetimes
are artificially extended to the end of the function. You can get the same
behavior on a non-debug build by adding a use of storage at the end of the
function. This will make Test1 and Test2 use the same amount of memory, and
Test3 and Test4 use the same amount of memory.
Now back to your question about why Test1/2 and Test3/4 use different
amounts of memory. As you would expect, SimpleObject and ComplexObject are
always the same size (20 and 24 bytes). The difference is that in case 1 and
2 you are just copying references for the string fields, so they all share
the same string objects. In cases 3 and 4, when you deserialize each object
separately a separate string is allocated for each (you can see this in the
CLRProfiler output).
If you expect a lot of duplicate strings, you can get this sharing by using
String.Intern (check out
http://msdn2.microsoft.com/en-us/library/system.string.intern.aspx) and
replacing each string with an interned version.
Hope this helps clear things up!
"Michael Cline" wrote:
Looks like on XP SP2 I only come up with 2 sets of memory sizes, one for the.
manually constructed object and one for those generated via the
XmlSerializer. The 2.0 Framework seems to make the analyzation completely
different.
I e-mailed you the code and results, following is the code.
using System;
using System.IO;
using System.Collections;
using System.Xml.Serialization;
namespace Memory
{
public class Anomoly
{
public static void Main( )
{
//Test1();
Test2();
//Test3();
//Test4();
}
public static void Test1( )
{
Hashtable storage = new Hashtable();
for( int i = 0; i < 10000; i++ )
{
ComplexObject tempVehicle = BuildObject();
storage.Add( i, tempVehicle );
}
GC.Collect();
Console.WriteLine( "Storage has been populated" );
Console.Read();
}
public static void Test2( )
{
Hashtable storage = new Hashtable();
for( int i = 0; i < 10000; i++ )
{
ComplexObject tempVehicle = BuildObject();
storage.Add( i, tempVehicle.DeepClone() );
}
GC.Collect();
Console.WriteLine( "Storage has been populated with manually created
clones" );
Console.Read();
}
public static void Test3( )
{
StreamWriter serializedWriter = new StreamWriter("C:\\Object.xml");
XmlSerializer serializer = new XmlSerializer( typeof(ComplexObject) );
ComplexObject objectToSerialize = BuildObject();
serializer.Serialize( serializedWriter, objectToSerialize );
serializedWriter.Close();
StreamReader serializedReader = new StreamReader( "C:\\Object.xml" );
string serializedString = serializedReader.ReadToEnd();
serializedReader.Close();
Hashtable storage = new Hashtable();
for( int i = 0; i < 10000; i++ )
{
StringReader objectReader = new StringReader( serializedString );
ComplexObject tempVehicle = serializer.Deserialize( objectReader )
as ComplexObject;
storage.Add( i, tempVehicle );
objectReader.Close();
}
GC.Collect();
Console.WriteLine( "Storage has been populated with XmlDeserialized
Objects" );
Console.Read();
}
public static void Test4( )
{
StreamWriter serializedWriter = new StreamWriter("C:\\Object.xml");
XmlSerializer serializer = new XmlSerializer( typeof(ComplexObject) );
ComplexObject objectToSerialize = BuildObject();
serializer.Serialize( serializedWriter, objectToSerialize );
serializedWriter.Close();
StreamReader serializedReader = new StreamReader( "C:\\Object.xml" );
string serializedString = serializedReader.ReadToEnd();
serializedReader.Close();
Hashtable storage = new Hashtable();
for( int i = 0; i < 10000; i++ )
{
StringReader objectReader = new StringReader( serializedString );
ComplexObject tempVehicle = serializer.Deserialize( objectReader )
as ComplexObject;
storage.Add( i, tempVehicle.DeepClone() );
objectReader.Close();
}
GC.Collect();
Console.WriteLine( "Storage has been populated with XmlDeserialized
Objects" );
Console.Read();
}
private static ComplexObject BuildObject()
{
SimpleObject tempPerson = new SimpleObject();
tempPerson.Irritable = true;
tempPerson.Age = 45;
tempPerson.Name = "John";
ComplexObject rc = new ComplexObject();
rc.Wheels = 4;
rc.Model = "Ford";
rc.Available = true;
rc.Person = tempPerson;
return rc;
}
}
public class SimpleObject
{
public SimpleObject(){}
private int age = 0;
private string name = string.Empty;
private bool irritable = false;
public int Age
{
get{return age;}
set{age = value;}
}
public string Name
{
get{return name;}
set{name = value;}
}
public bool Irritable
{
get{return irritable;}
set{irritable = value;}
}
}
public class ComplexObject
{
public ComplexObject(){}
private SimpleObject person = null;
private int wheels = 0;
private string model = string.Empty;
private bool available = false;
public SimpleObject Person
{
get{return person;}
set{person = value;}
}
public int Wheels
{
get{return wheels;}
set{wheels = value;}
}
public string Model
{
get{return model;}
set{model = value;}
}
public bool Available
{
get{return available;}
set{available = value;}
}
public ComplexObject DeepClone()
{
ComplexObject rc = new ComplexObject();
rc.Wheels = wheels;
rc.Model = model;
rc.Available = available;
if( null != person )
{
SimpleObject tempPerson = new SimpleObject();
tempPerson.Irritable = Person.Irritable;
tempPerson.Age = Person.Age;
tempPerson.Name = Person.Name;
rc.Person = tempPerson;
}
return rc;
}
}
}
- References:
- RE: XmlSerialization Object Memory Usage
- From: Michael Cline
- RE: XmlSerialization Object Memory Usage
- Prev by Date: Re: Performance issues on production server running VS 2003 application
- Next by Date: RE: Memory growth halts with use of Profiler - bug in .NET service
- Previous by thread: RE: XmlSerialization Object Memory Usage
- Next by thread: Re: System uses 50% of cpu usage on computer at all times.
- Index(es):
Relevant Pages
|