3

The Problem.

  • C# WCF Client/Server Application using Net TCP Binding (Publisher/Subscriber Pattern).
  • Client-side keeps crashing with an OutOfMemoryException.
  • When I run Task Manager along with the client, I can see the Memory Usage column increase until the application crashes.
  • Intention is for multiple instances of the client to be running on separate machines.

Scenario

  • I have a client/server application.
  • Publisher/Subscriber Design Pattern.
  • On the server-side there are 6 dictionaries that make up a cache, each containing a custom object as a value.
  • Each set of dictionary values gets updated every 5 seconds as part of a while loop.
  • At the end of the 5 second loop, the 6 dictionaries are added to a datacontract object, each as a different data member.
  • The data contract object is then sent over the wire to the client, where there are 6 more dictionaries.
  • I then loop through each data contract dictionary, and either add to or update the contents of it's client-side equivalent, depending on whether the values already exist or not.

Summary

  • 6 dictionaries server-side.
  • 6 serializable dictionaries in the data contract.
  • 6 bindable dictionaries client-side.
  • WCF using Net TCP Binding to transport data over the wire.

Specification

  • C# .Net 3.5
  • Client-side using one DevExpress form and 9 DX gridviews & tab controls.
  • Most of the custom objects containg a dictionary of "sub assets". - I have used a bindable dictionary for this property, which I imagine creates overhead when you have a few hundred objects (although I don't think using a serializable dictionary instead would make much difference, as they both contain the same code for serialization).
  • Bindings on both sides are programmatically created once at the start and contain the same settings (see below).

    NetTcpBinding netTcpBinding = new NetTcpBinding(SecurityMode.None);
    
    EndpointAddress endpointAddress = new EndpointAddress(EndpoindAddress);
    InstanceContext context = new InstanceContext(callbackinstance);
    
    netTcpBinding.MaxConnections = 5;
    netTcpBinding.MaxBufferSize = 2147483647;
    netTcpBinding.MaxBufferPoolSize = 2147483647;
    netTcpBinding.MaxReceivedMessageSize = 2147483647;
    netTcpBinding.ReceiveTimeout = TimeSpan.MaxValue;
    netTcpBinding.CloseTimeout = TimeSpan.MaxValue;
    netTcpBinding.TransferMode = TransferMode.Buffered;
    netTcpBinding.ListenBacklog = 5;
    
    DuplexChannelFactory<ISubscription> channelFactory =
       new DuplexChannelFactory<ISubscription>(
              new InstanceContext(this), 
              netTcpBinding,
              endpointAddress);
    
    proxy = channelFactory.CreateChannel();
    

My Questions

  • How can I prevent the client memory usage from growing constantly?
  • Would the memory usage on the client be significantly lower if I sent only Generic Lists of objects as opposed to serializable dictionaries?
  • Have I setup my binding configurations correctly for this kind of implementation?
  • Any other suggestions for fixing this memory problem would be greatly appreciated.
Gustavo Mori
  • 8,319
  • 3
  • 38
  • 52
Goober
  • 13,146
  • 50
  • 126
  • 195
  • 4
    given the number of questions you've asked, and the low rate of acceptance and upvotes, can you explain the incentive to help you? – Mitch Wheat Nov 08 '10 at 10:18
  • We use IE6 in work, I can't accept as the JScript on the acceptance buttons doesn't work, and it's a corporate firm where everything is locked down heavily I'm afraid. I don't tend to use the internet much from home, so I don't get a chance to accept answers much. Plus you're forgetting the fact that sometimes there might be 20 answers, but they might all be rubbish and irrelevant/incorrect. – Goober Nov 08 '10 at 10:41
  • 2
    Well, SO is not for everybody. I'd recommend expertsexchange. – Hans Passant Nov 08 '10 at 11:04
  • I'm struggling to see why you have such a problem with this? – Goober Nov 08 '10 at 11:14
  • Because it is very discouraging and especially with such a very heavy question, it will scare people away. You will make a lot of people happy when you take the time to accept an answer for your questions. People invest time into answering your questions and if you need to answer them from home because you can't from work, it seems like a fare trade to actually spend that time. – Pieter van Ginkel Nov 08 '10 at 19:20

3 Answers3

1

•How can I prevent the client-interface from just growing exponentially in terms of memory usage?

Erm, its not growing exponentially, but make sure you dont have stray references, in particular look for events and lambda's that may have references to your stray objects

•Would the memory usage on the client-side be much lower if I sent only Generic Lists of objects as opposed to serializable dictionaries?

I doubt it.

•Have I setup my binding configurations correctly for this kind of implementation?

Dont see any obvious issue with them

•Any other suggestions for fixing this memory problem would be greatly appreciated.

Look up Windbg, it requires time to learn properly, but it can help you see what has references to what... it may not be what you expect

stevenrcfox
  • 1,547
  • 1
  • 14
  • 37
0

Maxing out the MaxBufferPoolSize to 2 GB (netTcpBinding.MaxBufferPoolSize = 2147483647;) is not a wise decision unless you have the RAM to spare.

WCF will keep on accumulating buffers and you may receive an OutOfMemoryException.

There's a good explanation here.

StuartLC
  • 104,537
  • 17
  • 209
  • 285
0

Are you making sure that you only have one ServiceChannelFactory and that WCF Channels are being opened as late as possible closed as early as possible?

tucaz
  • 6,524
  • 6
  • 37
  • 60