Durante l'esecuzione delle chiamate all'API SOAP AXL di Cisco tramite WCF viene utilizzato un elevato numero di CPU. Comincio creando un client del modello di servizio utilizzando classi generate da wsdl. Sto usando basichttpbinding e transfermode come buffer. Quando si esegue una chiamata, la CPU raggiunge il limite massimo e un profilo CPU mostra che il 96% del tempo della CPU è a [email protected]
da clr.dll chiamato dopo chiamate come base.Channel.getPhone(request);
. Più correttamente, la chiamata espande il core della CPU su cui è in esecuzione il processo.WCF alza CPU durante l'attesa della funzione _TransparantProxyStub_CrossContext durante la chiamata
Ecco un elemento di cattura della creazione client dal WSDL generare
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class AXLPortClient : System.ServiceModel.ClientBase<AxlNetClient.AXLPort>, AxlNetClient.AXLPort
{
public AXLPortClient()
{
}
public AXLPortClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
...
Questo è come genero il cliente:
public class AxlClientFactory : IAxlClientFactory
{
private const string AxlEndpointUrlFormat = "https://{0}:8443/axl/";
public AXLPortClient CreateClient(IUcClientSettings settings)
{
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
ServicePointManager.Expect100Continue = false;
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
basicHttpBinding.MaxReceivedMessageSize = 20000000;
basicHttpBinding.MaxBufferSize = 20000000;
basicHttpBinding.MaxBufferPoolSize = 20000000;
basicHttpBinding.ReaderQuotas.MaxDepth = 32;
basicHttpBinding.ReaderQuotas.MaxArrayLength = 20000000;
basicHttpBinding.ReaderQuotas.MaxStringContentLength = 20000000;
basicHttpBinding.TransferMode = TransferMode.Buffered;
//basicHttpBinding.UseDefaultWebProxy = false;
var axlEndpointUrl = string.Format(AxlEndpointUrlFormat, settings.Server);
var endpointAddress = new EndpointAddress(axlEndpointUrl);
var axlClient = new AXLPortClient(basicHttpBinding, endpointAddress);
axlClient.ClientCredentials.UserName.UserName = settings.User;
axlClient.ClientCredentials.UserName.Password = settings.Password;
return axlClient;
}
}
Il codice WSDL generato per l'API AXL è molto grande. Sia le chiamate iniziali che quelle successive hanno il problema della CPU, sebbene le chiamate successive siano più veloci. C'è altro che posso fare per eseguire il debug di questo problema? C'è un modo per ridurre questo elevato utilizzo della CPU?
Aggiornamento
Un po 'più di informazioni con la grazia:
Ho creato le classi C# in questo modo:
svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient
È necessario scaricare il WSDL per AXL API di Cisco da un sistema di gestione delle chiamate. Sto usando la versione 10.5 dell'API. Credo che un importante rallentamento sia legato all'elaborazione XML. Il WSDL per l'API è enorme con le classi risultanti che creano 538406 linee di codice!
Aggiornamento 2
ho acceso WCF tracciando con tutti i livelli. La maggiore differenza di tempo è nell'azione di processo tra "Un messaggio è stato scritto" e "Inviato un messaggio su un canale" in cui passa quasi un intero minuto tra queste due azioni. Altre attività (costrutto canale, open clientbase e close clientbase) vengono eseguite tutte relativamente veloci.
Update 3
Ho fatto due modifiche alle classi client generato. Innanzitutto, ho rimosso lo ServiceKnownTypeAttribute
da tutti i contratti operativi. In secondo luogo, ho rimosso XmlIncludeAtribute da alcune classi serializzabili. Queste due modifiche hanno ridotto la dimensione del file del client generato di oltre il 50% e hanno avuto un impatto minimo sui tempi di test (una riduzione di circa 10 secondi su un risultato del test degli anni '70).
Ho anche notato che ho circa 900 contratti di operazione per un'unica interfaccia di servizio e endpoint. Ciò è dovuto al wsdl per l'API AXL che raggruppa tutte le operazioni in un singolo spazio dei nomi. Sto pensando di rompere questo, ma ciò significherebbe creare più clientbase che implementerebbero ciascuna un'interfaccia ridotta e finiranno per rompere tutto ciò che implementa questa libreria wcf.
Update 4
Sembra che il numero di operazioni è il problema centrale. Sono stato in grado di separare le operazioni e le definizioni dell'interfaccia in base al verbo (ad es.ottiene, aggiunge, ecc.) nella propria base client e nell'interfaccia (un processo molto lento che utilizza il testo sublime e regex come resharper e codemaid non possono gestire il file di grandi dimensioni che è ancora 250K + linee). Un test del client "Get" con circa 150 operazioni definite ha comportato un'esecuzione di 10 secondi per getPhone rispetto a un precedente risultato di 60 secondi. Questo è ancora molto più lento di quanto dovrebbe essere, semplicemente creando questa operazione nei risultati del violinista in un'esecuzione di 2 secondi. La soluzione probabilmente ridurrà ulteriormente il conteggio delle operazioni cercando di separare ulteriormente le operazioni. Tuttavia, questo aggiunge un nuovo problema di rompere tutti i sistemi che hanno utilizzato questa libreria come un singolo client.
Poiché non si tratta di una risposta definitiva, condividerò un'esperienza simile. Avevo creato un wcf con molte operazioni e grandi wsdl. Ho avuto un problema simile con l'utilizzo della CPU alta. Avevo risolto il problema, impostando l'assembly per la serializzazione sul progetto wcf. Nelle proprietà del progetto, sezione build, puoi provare a impostare "Genera assembly di serializzazione" su "On" e anche impostare la "Documentazione Xml" nella cartella "bin \ release" o "bin \ debug" a seconda di come stai costruire la tua soluzione. Fammi sapere se funziona così posso scrivere una risposta e pubblicare di più su questa soluzione alternativa. –
Non ho ottenuto alcun aumento delle prestazioni dall'impostazione di queste due opzioni. Stavo eseguendo test unitari nella configurazione di rilascio con serializzazione impostata su auto che in base a questo (https://stackoverflow.com/questions/9187248/when-to-change-the-generate-serialization-assembly-value) indica che la serializzazione è attiva già. La documentazione Xml serve per tradurre i commenti in afik di intelligenza, ma ho provato comunque. –