Я пытаюсь понять, почему первый вызов WCF после запуска клиентского приложения занимает гораздо больше времени по сравнению со вторым.
Что я сделал, чтобы проверить это:
- Реализован простой сам сервер WCF и консольный клиент.
- Сервер разогревается. Я запускаю его и вызываю метод несколько раз перед запуском теста.
- Связывание
basicHttpBinding
уменьшает затраты на сеть и безопасность. - Сценарий тестирования - запустите консольное клиентское приложение, выполнив два одинаковых вызова службы WCF в строке.
В моих тестах я вижу ~ 700 миллисекунд для первого вызова и ~ 3 миллисекунды для второго вызова.
Кажется, что для JIT-компилятора слишком много времени. Я бы согласился, если это время используется для инициализации некоторой сложной инфраструктуры, такой как ObjectContext
в Entity Framework, но мой код очень прост и прокси-классы уже скомпилированы.
Я также пробовал привязку netNamedPipeBinding
. Результат доказывает шаблон - первый вызов занимает ~ 800 мс, второй вызов занимает ~ 8 мс.
Поймите, если кто-нибудь сможет объяснить, почему первый вызов службы занимает так много времени.
Протестировано в Win 7 64 бит.
Моя реализация ниже.
Contract:
[ServiceContract]
public interface ICounter
{
[OperationContract]
int Add(int num);
}
Реализация службы:
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;
}
}
Реализация сервера:
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();
}
}
}
Конфигурация сервера:
<?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>
Реализация клиента (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;
Функция, которая содержит этот код, который два раза подряд указан.
Конфигурация клиента:
<?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>