4 Comments

  • Well I don't know about the "XmlSerilizer" but I've heard the "XmlSerializer" may be buggy ;-)

  • Yes its a memory leak -- its NEVER reclaimed by the GC. Its the actual dynamic assembly that is "lost", which isn't managed memory. Some of the .net memory counters do increase a little, but its the private bytes of the process that go through the roof. Run this code snippet as the only file in a console app with performance monitor. With the leakMemory variable set to true, then run it again with leakMemory set to false. The only difference is whether or not the XmlSerializer is created each time, or only once. My last test had a fatal memory crash after leaking almost 500MB, which had long since pushed me far into the page file. All memory was reclaimed when the process was killed, or ended if you make it that far, but the GC never manages it or reclaims it. Can we switch to a simpler constructor? No. We could possibly use a different one with more work, but the other links I provided on my blog indicate that most of the constructors, except the very simplest, leak dynamic assemblies.



    using System;

    using System.IO;

    using System.Text;

    using System.Xml.Serialization;



    namespace XmlLeak

    {

    class Global

    {

    private static bool leakMemory = true;

    private static XmlSerializer serial = null;



    [STAThread]

    private static void Main(string[] args) {

    for (int index = 0; index < 1000000; index++) {

    Test test = new Test();

    test.Id = index;

    test.Time = DateTime.Now;

    StringBuilder builder = new StringBuilder();

    StringWriter writer = new StringWriter(builder);

    if (leakMemory || serial == null) {

    serial = new XmlSerializer(typeof(Base), new Type[] {typeof(Test)});

    }

    serial.Serialize(writer, test);

    string xml = builder.ToString();

    }

    }

    }



    [Serializable()]

    public class Test : Base

    {

    private DateTime time;

    public DateTime Time {

    get { return time; }

    set { time = value; }

    }

    }



    [Serializable()]

    public class Base

    {

    private int id;

    public int Id {

    get { return id; }

    set { id = value; }

    }

    }

    }

  • Looking at it through Reflector, the only two constructors that it is supported for are:



    public XmlSerializer(Type type);

    public XmlSerializer(Type type, string defaultNamespace);



    The first constructor just forwards to the second with a null for the second parameter. The second ctor's body looks like (from Reflector):



    XmlReflectionImporter importer1;

    TempAssemblyCache cache1;

    this.events = 0;

    base..ctor();

    this.events.sender = this;

    this.tempAssembly = XmlSerializer.Cache[defaultNamespace,type];

    if(this.tempAssembly == null)

    {

    cache1 = XmlSerializer.cache;

    Monitor.Enter(XmlSerializer.cache);

    try

    {

    this.tempAssembly = XmlSerializer.Cache[defaultNamespace,type];

    if(this.tempAssembly == null)

    {

    importer1 = new XmlReflectionImporter(defaultNamespace);

    this.tempAssembly = XmlSerializer.GenerateTempAssembly(importer1.ImportTypeMapping(type));

    XmlSerializer.cache.Add(defaultNamespace,type,this.tempAssembly);

    }

    }

    finally

    {

    Monitor.Exit(cache1);

    }

    }



    The key for the cache (which is just a Hashtable) is the defaultNamespace that is passed in. Since the defaultNamespace is used for the key, that would not work for the following constructor signatures:



    public XmlSerializer(Type type, Type[] extraTypes);

    public XmlSerializer(Type type, System.Xml.Serialization.XmlAttributeOverrides overrides);

    public XmlSerializer(Type type, System.Xml.Serialization.XmlRootAttribute root);

    public XmlSerializer(System.Xml.Serialization.XmlTypeMapping xmlTypeMapping);

  • Please let me know if you're looking for a article author for your weblog. You have some really good articles and I believe I would be a good asset. If you ever want to take some of the load off, I'd
    absolutely love to write some articles for your blog in exchange
    for a link back to mine. Please send me an e-mail if interested.

    Regards!

Comments have been disabled for this content.