Sto cercando di capire perché la prima chiamata WCF dopo l'avvio dell'applicazione client richiede molto più tempo rispetto alla seconda.Perché la prima chiamata del client WCF è lenta?
Quello che ho fatto per provare che:
- Implementato semplice auto ospitato WCF server e il client della console.
- Il server è in fase di riscaldamento - Lo eseguo e chiamo il metodo più volte prima di eseguire il test.
- Il collegamento è
basicHttpBinding
per ridurre i costi di rete e di sicurezza. - Scenario di test: avviare l'app client della console, effettuando due chiamate di servizio WCF identiche in una riga.
Nei miei test vedo ~ 700 millisecondi per la prima chiamata e ~ 3 millisecondi per la seconda chiamata.
Quasi un secondo sembra essere troppo tempo per il compilatore JIT. Accetterei se quel tempo venga utilizzato per inizializzare un'infrastruttura complicata come ObjectContext
in Entity Framework ma il mio codice è molto semplice e le classi proxy sono già compilate.
Ho anche provato il binding netNamedPipeBinding
. Il risultato mostra un pattern - la prima chiamata dura circa 800 ms, la seconda richiede circa 8 ms.
Apprezzeranno se qualcuno può spiegare perché la prima chiamata di servizio richiede così tanto tempo.
Testato in Win 7 64 bit.
La mia implementazione è di seguito.
contratto:
[ServiceContract]
public interface ICounter
{
[OperationContract]
int Add(int num);
}
servizio di implementazione:
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 Implementazione:
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();
}
}
}
Configurazione del server:
<?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>
implementazione client (CounterProxy
viene generato dal riferimento di servizio):
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;
funzione che contiene tale codice chiamato due volte di seguito.
configurazione client:
<?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>
Probabilmente il caricamento/compilato l'oggetto proxy prima volta intorno, i serializzatori XML ecc Se si guarda la finestra di output dovresti vedere qualcosa come "Loaded assembly x54fjfj3fj" che è un client WCF compilato. –
Incolpare i controlli di sicurezza e altre 100 incognite. C'è molto più binari coinvolti di ciò che è nel servizio distribuito. Per eseguire il debug del servizio, utilizzare i traccianti nei registri di configurazione e di visita, che mostreranno passaggi in millisecondi su che cosa si spende esattamente il tempo. Vedrai qualcosa come Autenticazione, filtri, ecc. Anche se hai qualsiasi cosa che funzioni come anonimo. –