can anyone tell us what’s wrong with this code below?
we have here an object serializer that should return an XML string of any object passed to it.
we’ve been scratching our heads over this one, as we have a program that calls this multiple times and we see our memory usage going sky high (and staying there even after the program was done).. we’ve done searches but to no avail. the stream object is inside a “using” statement so we thought this was supposed to be disposed on its own.. help please.
public static string ToXML(this IMessage m)
{
try
{
var serializer = SerializerFactory.Create(m.GetType());
using (var stream = new MemoryStream())
{
serializer.Serialize(new[] { m }, stream);
stream.Position = 0;
var s = Encoding.ASCII.GetString(stream.ToArray());
return s;
}
}
catch (Exception e)
{
return string.Format("Message unserializable: {0}", e.Message);
}
}
btw SerializerFactory looks like this:
public class SerializerFactory
{
public static IMessageSerializer Create(Type t)
{
var types = new List<Type> { t };
var mapper = new MessageMapper();
mapper.Initialize(types);
var serializer = new XmlMessageSerializer(mapper);
serializer.Initialize(types);
return serializer;
}
}
There is nothing hugely wrong with that code; note that
usingis essentially a no-op on aMemoryStream, since it only has managed resources, and managed resources are the domain of the GC; it is normal for the GC not to worry hugely until it makes sense to collect some memory, so I wouldn’t stress too much – or: if there is a problem, it probably isn’t this.One observation, though, would be that you can avoid a buffer in the encode step:
and actually, I’d be tempted to use UTF8 by default, not ASCII.
A final thought: is your
SerializerFactoryitself doing something that leaks? For example, are you creating anew XmlSerializer(...)via any of the more complex constructors? The simplest form:is fine – it internally caches the internal/actual serializer per-type, and re-uses this for each
XmlSerializerinstance created this way. However, it does not do this caching for the more complex constructor overloads: it creates and loads a new dynamic assembly each time. And assemblies loaded in this way are never unloaded – so yes, that can cause a memory leak. I would be very keen to see how the serializer instances are created, to see if that is the actual problem. Note that such cases are usually very easy to fix by creating your own serializer-cache in the factory: