2

I have a UWP media app which is unable to stay below the 128MB for Xbox One running in background mode. Using the memory profiler, it seems that JSON.Net is utilizing the most resources both before deserialization has even started and after deserialization has finished and garbage collection has been forced.

Based on everything I've read, I'm instantiating a local DefaultContractResolver, which should not cache resources. I'm also deserializing from a stream, which according to the JSON.Net "Performance Tips" is the most memory efficient way to process json. I'm at a loss on why so many resources are still being held on to after garbage collection.

Before deserialization:

enter image description here

After deserialization and forced garbage collection:

enter image description here

Deserialization code:

public class JsonExtensions
{
    public T DeserializeStringNoCache<T>(string json, JsonSerializerSettings settings = null)
    {
        using (Stream s = StringHelper.GenerateStreamFromString(json))
        using (StreamReader sr = new StreamReader(s))
        using (JsonReader reader = new JsonTextReader(sr))
        {
            JsonSerializer serializer = new JsonSerializer();
            serializer.ContractResolver = new DefaultContractResolver();
            return serializer.Deserialize<T>(reader);
        }
    }
}
Rexfelis
  • 57
  • 3
  • 10
  • 1
    *I'm also deserializing from a stream, which according ...* **not true at all** you already have string so making stream from it takes even more memory... "Performance Tips" says that if you can have stream (like in http request) you should use it instead converting its content to string – Selvin Mar 19 '19 at 23:49
  • also you are talking about 128MB and showing something that takes 2MB at most ... you still have 126MB free ... – Selvin Mar 19 '19 at 23:58
  • In general, your observation is correct: Json.NET does cache reflected type information to improve performance, which does consume memory for the remainder of the session. This is intended functionality and not a bug, see [Does Json.NET cache types' serialization information?](https://stackoverflow.com/q/33557737/3744182). There does seem to be a memory leak specifically with caching the type information of `enum` values in Json.NET 12, see [Memory leak using enumeration in Newtonsoft.Json v12 #1991](https://github.com/JamesNK/Newtonsoft.Json/issues/1991), but that doesn't seem to apply here. – dbc Mar 20 '19 at 00:18
  • It will cache the type. – lindexi Mar 20 '19 at 00:19
  • I misread the tips page and switched my code back to what I originally had which was creating a local contract resolver without a stream. Since the types are cached, I probably need to look for memory optimizations elsewhere in my project. – Rexfelis Mar 20 '19 at 00:45
  • @Rexfelis - then can this question be closed as a duplicate of [Can Json.NET serialize / deserialize to / from a stream?](https://stackoverflow.com/a/17788118) and [Does Json.NET cache types' serialization information?](https://stackoverflow.com/q/33557737/3744182) or do you still need help? [Parsing large json file in .NET](https://stackoverflow.com/q/32227436) and [How to parse huge JSON file as stream in Json.NET?](https://stackoverflow.com/q/43747477) might give you some ideas. – dbc Mar 20 '19 at 01:09
  • Thanks for the links and yes it can be closed as a dupe. – Rexfelis Mar 20 '19 at 01:53
  • It turns out the memory issue is due to the XBox One holding onto UI resources that should be garbage collected. No fix yet from Microsoft, but hopefully in the next update. After doing extensive memory profiling on my app, it was always well under the 128MB limit. In addition, a bug exists which prevents VS2017 from running memory profiler on the Xbox One. – Rexfelis Mar 31 '19 at 22:35

0 Answers0