为什么第一个WCF客户端调用慢? [英] Why is the first WCF client call slow?

查看:521
本文介绍了为什么第一个WCF客户端调用慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出为什么客户端应用程序启动后的第一个WCF调用需要比较第二个更多的时间。

我所做的测试是:

  1. 在实现简单的自我承载WCF服务器和控制台的客户端。
  2. 服务器预热 - 我在运行测试之前运行它,并调用方法几次
  3. 绑定是 basicHttpBinding的来减少网络和安全的开销。
  4. 在测试场景 - 启动控制台客户端应用程序,使得在连续两个相同的WCF服务电话。

在我的测试中,我看到〜700毫秒的第一个电话,并〜3毫秒的第二个电话。

将近二似乎太多时间,JIT编译器。我会接受,如果那个时候是用来初始化一些复杂的基础设施,如的ObjectContext 在实体框架,但我的code是非常简单和代理类已经被编译。

我也试过 netNamedPipeBinding 绑定。结果证明模式 - 第一个电话大约需要800毫秒,第二个电话取〜8毫秒

请问AP preciate,如果有人可以解释为什么第一个服务调用花费这么多的时间。

测试在Win 7 64位。

我的实现如下。

合同:

  [的ServiceContract]
公共接口ICounter
{
        [OperationContract的]
        INT添加(INT NUM);
}
 

服务实现:

 公共类CounterService:ICounter
{
        私人诠释_value = 0;

        公众诠释添加(INT NUM)
        {
            _value + = NUM​​;
            Console.WriteLine(方法添加调用参数{0}方法返回{1},NUM,_value);
            返回_value;
        }
}
 

服务器实施:

 类节目
{
    静态无效的主要(字串[] args)
    {
        乌里baseAddress =新的URI(HTTP://本地主机:8080 /服务);

        //创建ServiceHost的。
        使用(ServiceHost的主机=新的ServiceHost(typeof运算(CounterService),baseAddress))
        {
            host.Open();

            Console.WriteLine(该服务已经准备好,在{0},baseAddress);
            Console.WriteLine(preSS<进入>停止服务);
            到Console.ReadLine();

            //关闭的ServiceHost。
            host.Close();
        }
    }
}
 

服务器配置:

 < XML版本=1.0编码=UTF-8&GT?;
<结构>
  < system.serviceModel>
    <服务>
      <服务名称=Server.CounterService>
        <端点地址=基地绑定=basicHttpBinding的NAME =baseDefault
          合同=Contract.ICounter/>
        <端点地址=net.pipe://本地主机/服务/ netNamedPipe
          绑定=netNamedPipeBindingNAME =netNamedPipeDefault合同=Contract.ICounter/>
        <端点地址=MEX绑定=mexHttpBinding合同=IMetadataExchange接口/>
      < /服务>
    < /服务>
    <行为>
      < serviceBehaviors>
        <行为NAME =>
          < serviceMetadata httpGetEnabled =真/>
        < /行为>
      < / serviceBehaviors>
    < /行为>
  < /system.serviceModel>
< /结构>
 

客户端实现( CounterProxy 是从服务中产生的引用):

 秒表,秒表=新的秒表();
stopWatch.Start();

使用(VAR代理=新CounterProxy.CounterClient(_endpointConfigurationName))
{
    输出= proxy.Add(1);
}

stopWatch.Stop();
//获取经过时间作为时间跨度值。
时间跨度TS = stopWatch.Elapsed;
 

功能包含code,连续叫了两个次。

客户端配置:

 < XML版本=1.0编码=UTF-8&GT?;
<结构>
  < system.serviceModel>
    <客户端>
      <端点地址=HTTP://本地主机:8080 /服务/基地绑定=basicHttpBinding的
          合同=CounterProxy.ICounter
          NAME =baseDefault/>
    < /客户>
  < /system.serviceModel>
< /结构>
 

解决方案

通常情况下,第一次调用花费更多的时间,因为在调用频道厂被实例化和prepared准备好沟通,而且耗费时间。创建的频道厂将被缓存并在后续调用重复使用,因此时间会少一些。

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

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>

解决方案

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

这篇关于为什么第一个WCF客户端调用慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆