16

I am trying to figure out why the first WCF call after client application start takes much more time comparing to second one.

What I did to test that:

  1. Implemented simple self hosted WCF Server and console client.
  2. Server IS warmed up - I run it and call method several times before running test.
  3. Binding is basicHttpBinding to reduce network and security overhead.
  4. Testing scenario - start console client app, making two identical WCF service calls in a row.

In my tests I see ~700 milliseconds for first call and ~3 milliseconds for second call.

Almost a second seems to be too much time for JIT compiler. I would accept if that time is used to initialize some complicated infrastructure like ObjectContext in Entity Framework but my code is very simple and proxy classes are already compiled.

I also tried netNamedPipeBinding binding. Result proves pattern - first call takes ~800 ms, second call takes ~8 ms.

Will appreciate if anybody can explain why the first service call takes so much time.

Tested in Win 7 64 bit.

My implementation is below.

Contract:

[ServiceContract]
public interface ICounter
{
        [OperationContract]
        int Add(int num);
}

Service Implementation:

public class CounterService: ICounter
{
        private int _value = 0;

        public int Add(int num)
        {
            _value += num;
            Console.WriteLine("Method Add called with argument {0}. Method  returned {1}", num, _value);
            return _value;
        }
}

Server Implementation:

class Program
{
    static void Main(string[] args)
    {
        Uri baseAddress = new Uri("http://localhost:8080/Service");

        // Create the ServiceHost.
        using (ServiceHost host = new ServiceHost(typeof(CounterService), baseAddress))
        {
            host.Open();

            Console.WriteLine("The service is ready at {0}", baseAddress);
            Console.WriteLine("Press <Enter> to stop the service.");
            Console.ReadLine();

            // Close the ServiceHost.
            host.Close();
        }
    }
}

Server Configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Server.CounterService">
        <endpoint address="base" binding="basicHttpBinding" name="baseDefault"
          contract="Contract.ICounter" />
        <endpoint address="net.pipe://localhost/Service/netNamedPipe"
          binding="netNamedPipeBinding" name="netNamedPipeDefault" contract="Contract.ICounter" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Client Implementation (CounterProxy is generated from service reference):

Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();

using (var proxy = new CounterProxy.CounterClient(_endpointConfigurationName))
{
    output = proxy.Add(1);
}

stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;

Function that contains that code called two times in a row.

Client Configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:8080/Service/base" binding="basicHttpBinding"
          contract="CounterProxy.ICounter"
          name="baseDefault" />
    </client>
  </system.serviceModel>
</configuration>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Dmitry Harnitski
  • 5,838
  • 1
  • 28
  • 43
  • Probably loading/compiled the proxy object first time around, the XML serialisers etc. If you watch the output window you should see something like "Loaded assembly x54fjfj3fj" which is a compiled WCF client. – ta.speot.is Jun 02 '12 at 04:41
  • 1
    I blame security checks and another 100 unknowns. There is way more binaries involved than what is in deployed service. To debug service use tracers in config and visit logs, they will show steps in milliseconds what exactly time is spent on. You wil see something like Authentication, filters, etc even if you have everything acting as anonymous. –  Jun 02 '12 at 04:46

4 Answers4

8

Usually the first call takes more time because in that call the Channel Factory is instantiated and prepared ready for the communication and that costs time. The created Channel Factory will be cached and reused in subsequent calls and so the time will be less.

http://social.msdn.microsoft.com/Forums/en/wcf/thread/43f89088-546b-46b0-adf8-214deb1741bd

VJAI
  • 32,167
  • 23
  • 102
  • 164
  • But this suggestion is for the client side, if I understand correctly. cant we do anything on the service side. It is not easy to say each client do that. – Emil Apr 22 '14 at 11:12
  • 1
    Looks like Microsoft is finally giving some control over this: https://msdn.microsoft.com/en-us/library/hh160401%28v=vs.110%29.aspx – userx Jun 11 '15 at 17:58
3

If you are making calls to your WCF service less frequently than 15 seconds (we observed needing to wait about 20 seconds in our application), this Microsoft blog appears to explain your problem: http://blogs.msdn.com/b/wenlong/archive/2010/02/11/why-does-wcf-become-slow-after-being-idle-for-15-seconds.aspx

The article also links to this entry which mentions a fix for SetMinThreads() which also appears to be a contributing problem: http://blogs.msdn.com/b/wenlong/archive/2010/02/11/why-are-wcf-responses-slow-and-setminthreads-does-not-work.aspx

userx
  • 3,769
  • 1
  • 23
  • 33
2

I have similar problem. So what we actually did, we wrote service that invoke WCF service per some interval. I know that it's not an elegant solution but it's working.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Gregory Nozik
  • 3,296
  • 3
  • 32
  • 47
  • Do you have any idea WHY it is happening? Seems that many people see it but nobody I know understands the reason. Thanks for response. – Dmitry Harnitski Jun 02 '12 at 04:52
  • 2
    Look at this , well written http://www.codeproject.com/Tips/114132/WCF-First-Call-Slow – Nick Aug 24 '12 at 20:49
  • What interval did you use? From what I can tell, the cache doesn't seem to be tied to the timeouts. But is less than 1 minute. – userx Jun 11 '15 at 17:51
2

I was seeing delays in the range of 30 seconds when I was first creating my service proxy instance which I knew must be related to some sort of network timeout.

In the end for me it was actually checks for the Certificate Revocation List that were being blocked or frustrated by the corporate proxy (yay Websense) as highlighted here: WCF service startup too slow? Have you thought to CRL check?.

For future reference and in case the link goes dead it came down to adding the following to the client config:

<configuration>
  <runtime>
    <generatePublisherEvidence enabled=“false”/>
  </runtime>
</configuration>
Shaun
  • 1,293
  • 16
  • 19
  • 2
    In the .NET Framework 4 and later, this element has no effect on assembly load times. For more information, see the "Security Policy Simplification" section in Security Changes in the .NET Framework.https://msdn.microsoft.com/en-us/library/dd233103(v=vs.100).aspx (switch to .NET 4.0) – Ludwo Nov 23 '16 at 09:38