Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Service Memory Leaks

I have a very small wcf service hosted in a console app.

[ServiceContract]
public interface IService1
{
    [OperationContract]
    void DoService();
}

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class Service1 : IService1
{
    public void DoService()
    {

    }
}

and its being called as

using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client())
{
    client.DoService(new DoServiceRequest());
    client.Close();
} 

Please remember that service is published on basicHttpBindings.

Problem

Now when i performed above client code in a loop of 1000 i found big difference between "All Heap bytes" and "Private Bytes" performance counters (i used .net memory profiler). After investigation i found some of the objects are not properly disposed following are the list of those objects (1000 undisposed instance were found --> equals to the client calls)

(namespace for all of them is System.ServiceModel.Channels)

HttpOutput.ListenerResponseHttpOutput.ListenerResponseOutputStream
BodyWriterMessage
BufferedMessage
HttpRequestContext.ListenerHttpContext.ListenerContextHttpInput.ListenerContextInputStream
HttpRequestContext.ListenerHttpContext 

Questions Why do we have lot of undisposed objects and how to control them.

Please Help

like image 328
Mubashar Avatar asked May 12 '10 11:05

Mubashar


2 Answers

You're requesting a new instance per call (InstanceContextMode=InstanceContextMode.PerCall). If there is no GC happening in the 1000 calls then the service instances will be uncollected. WCF requires you implement IDisposable

From MSDN : Discover Mighty Instance Management Techniques For Developing WCF Apps

Per-Call Services Per-call services are the Windows Communication Foundation default instantiation mode. When the service type is configured for per-call activation, a service instance, a common language runtime (CLR) object, exists only while a client call is in progress. Every client request gets a new dedicated service instance. Figure 2 illustrates how this single-call activation works.

Figure 2 Per-Call Instantiation
(source: microsoft.com)

  1. The client calls the proxy and the proxy forwards the call to the service.
  2. Windows Communication Foundation creates a service instance and calls the method on it.
  3. After the method call returns, if the object implements IDisposable, then Windows Communication Foundation calls IDisposable.Dispose on it.
like image 168
Preet Sangha Avatar answered Sep 17 '22 21:09

Preet Sangha


Did you by any chance enable performance counters? Like below?

<system.serviceModel>
  <diagnostics performanceCounters="All" />
  ..
</system.serviceModel>

In paragraph "Increasing Memory Size for Performance Counters", from this link: http://msdn.microsoft.com/en-us/library/ms735098.aspx

there's mention of a "rogue" Private Bytes count when WCF performance counters are enabled. Changing it into ServiceOnly or completely disabling it (Off) may do the trick.

like image 20
Bram Avatar answered Sep 17 '22 21:09

Bram