为什么第一个WCF客户端调用速度慢?

Dmi*_*ski 14 .net performance wcf .net-4.0 basichttpbinding

我试图弄清楚为什么客户端应用程序启动后第一次WCF调用与第二次调用相比需要更多时间.

我做了什么测试:

  1. 实现了简单的自托管WCF服务器和控制台客户端.
  2. 服务器IS预热 - 我运行它并在运行测试之前多次调用方法.
  3. 绑定是basicHttpBinding为了减少网络和安全开销.
  4. 测试场景 - 启动控制台客户端应用程序,连续进行两次相同的WCF服务调用.

在我的测试中,我看到第一次呼叫约700毫秒,第二次呼叫约3毫秒.

几乎一秒似乎是JIT编译器的太多时间.我会接受,如果那个时间用于初始化一些复杂的基础设施,如ObjectContext实体框架,但我的代码非常简单,代理类已经编译.

我也试过netNamedPipeBinding绑定.结果证明模式 - 第一次调用需要~800 ms,第二次调用需要~8 ms.

如果有人能解释为什么第一次服务电话会花费这么多时间,我们将不胜感激.

在Win 7 64位中测试过.

我的实现如下.

合同:

[ServiceContract]
public interface ICounter
{
        [OperationContract]
        int Add(int num);
}
Run Code Online (Sandbox Code Playgroud)

服务实施:

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;
        }
}
Run Code Online (Sandbox Code Playgroud)

服务器实施:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

服务器配置:

<?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>
Run Code Online (Sandbox Code Playgroud)

客户端实现(CounterProxy从服务引用生成):

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;
Run Code Online (Sandbox Code Playgroud)

包含连续两次调用的代码的函数.

客户端配置:

<?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>
Run Code Online (Sandbox Code Playgroud)

VJA*_*JAI 7

通常,第一次调用需要更多时间,因为在该调用中,Channel Factory实例化并准备好进行通信并且花费时间.创建的内容Channel Factory将在后续调用中缓存和重用,因此时间会更短.

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