0

How can I improve performance when mapping really big data structure to other classes for serialization / web api?

I have this class

interface INode
{
    string Id { get; }

    INode Parent { get; }
    MyCollection<INode> Children { get; }
}

class MyCollection<T> : IEnumerable<T> where T : INode
{
    private IDictionary<string, T> nodes;

    public MyCollection(IEnumerable<T> nodeCollection)
    {
        nodes = nodeCollection.ToDictionary(t => t.Id);
    }

    public IEnumerator<T> GetEnumerator()
        => nodes.Values.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator()
        => GetEnumerator();
}

So when I initialize my tree I recursively create collections under collections, and there's pretty big performance loss, but I guess there's nothing you can do, because ToDictionary() method iterates through the collection and takes its time.

But when I pass this class to web api, I need to map it first to some other class because otherwise serializer tells me that there's cyclical references (Nodes[0] -> Parent -> Nodes[0] -> Parent -> Nodes[0]). So I map my structure recursively to this class:

class DomainNode {
    public string Id { get; set; }

    public string ParentId { get; set; }
    public IEnumerable<DomainNode> Children { get; set; }
}

by setting all the properties manually (without e.g. Automapper for now).

For big datasets, theres very big performance impact. When I load some mediocre collection, it takes full 7 seconds to get my response. It there any faster way? Maybe with hacks?

If there's special instructions how to do it with Json.Net / Web.Api (Owin) it would be great.

Ivan Zyranau
  • 879
  • 2
  • 14
  • 33
  • 1
    See JsonIgnoreAttribute to exclude the Parent property during serialization. – Biscuits Aug 11 '16 at 18:59
  • I can't set JsonIgnore on worker class because it is in separate assembly and does not know anything about web api or any other consumer, also it doesn't include Json.Net package. I asked for Json.Net solution because I think maybe there's a way to configure this dynamically for some class. If it helps, I'm using Autofac... – Ivan Zyranau Aug 11 '16 at 19:24
  • 1
    Could you give an [mcve] showing what your classes might look like? I'm having a little trouble imagining your exact problem since your `INode` and `MyCollection` don't compile. – dbc Aug 11 '16 at 19:39
  • 1
    Did you try implementing a custom IContractResolver? http://stackoverflow.com/a/18548894/2707705 – Biscuits Aug 11 '16 at 19:42
  • @dbc I updated the question – Ivan Zyranau Aug 11 '16 at 19:55
  • @Biscuits no, I did not. Can I set custom ContractResolver for single custom class? – Ivan Zyranau Aug 11 '16 at 19:57

0 Answers0