4

According to MSDN XmlSerializer Class section "Dynamically Generated Assemblies" the XmlSerializer produces memory leaks when using certain constructors. I wonder if the

XmlSerializer.FromTypes(Type[])

method produces memory leaks, too?

EDIT:

I'm experiencing memory problems, when using the FromTypes method. So i started some investigations:

for (int i = 0; i < 1000; i++)
{
    DummyObject content = new DummyObject()
    {
        Age = 29,
        Location = "London",
        Name = "Pete"
    };
    XmlSerializer serializer = XmlSerializer.FromTypes(new[] { content.GetType() })[0];
    using (TextWriter textWriter = new StreamWriter($@"D:\test\array\{i}.xml"))
    {
        serializer.Serialize(textWriter, content);
    }
}

After executing the above code a few times the diagnostic tools of Visual Studio 2015 show the following:

Diagnostic Tools Image

The garbage collector runs, but it seems like the dynamically generated assemblies are flooding the memory. It would be interesting to know which constructor the FromTypes method internally uses. So, the FromTypes method produces memory leaks, too?

ttP
  • 43
  • 4
  • Are you experiencing specific issues with this particular method? Or is this just a hypothetical waxing? – gravity Oct 18 '16 at 17:16
  • I'm experiencing memory problems, when using this method. I added some code and the result of the visual studio diagnostic tools to this post to show the behavior. It seems as if the method produces memory leaks. – ttP Oct 19 '16 at 11:47
  • see also: https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer – dummy Aug 17 '18 at 09:41

1 Answers1

2

I slightly changed your code - run a loop 3000 times instead of 1000 and write serialized data into memory stream instead of file, and profile it with dotMemory. (I found using VS that RuntimeType instances are leaked, but did not find how to see where they were created).

At the end app occupied about a 1Mb of memory (I did not received a result of 500Mb as on your screenshot) but it's obviously a leak here. enter image description here

Then opened all new objects created between the first and the fourth snapshots placed in Gen2 heap and found out that most of them are (as I mentioned above) instances of RuntimeType. enter image description here

Opened them and saw that there are five almost equal sized groups of them. enter image description here

So, the answer is "yes, this method produces a memory leak"

Below five stack traces where these objects were allocated

--------- 1 -------------- Allocated: 83580 B in 2985 objects

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationWriterILGen.GenerateEnd() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() Folded items [AllThreadsRoot]

--------- 2 -------------- Allocated: 83552 B in 2984 objects

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationReaderILGen.GenerateEnd() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() Folded items [AllThreadsRoot]

--------- 3 -------------- Allocated: 83552 B in 2984 objects

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationILGen.GenerateBaseSerializer() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() Folded items [AllThreadsRoot]

--------- 4 -------------- Allocated: 83552 B in 2984 objects

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationILGen.GenerateTypedSerializer() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() Folded items [AllThreadsRoot]

--------- 5 -------------- Allocated: 83552 B in 2984 objects

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationILGen.GenerateSerializerContract() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() Folded items [AllThreadsRoot]

Ed Pavlov
  • 2,353
  • 2
  • 19
  • 25
  • 1
    Thanks for your answer! This confirms my suspicion about this method. Now I'm caching the XmlSerializer instances, to reuse them and to not flood Memory. – ttP Oct 27 '16 at 09:54