WCF maxes CPU while waiting for _TransparantProxyStub_CrossContext function during a call

I get heavy CPU usage when accessing the Cisco AXL SOAP API using WCF. I start by creating a client base for the service model using the generated classes from wsdl. I use basichttpbinding and transfermode as buffered. When a call is made, the CPU fails, and the CPU profile shows that 96% of the processor time is in _TransparentProxyStub_CrossContext@0 from clr.dll, called after calls such as base.Channel.getPhone(request); . Rather, the call displays the core of the processor in which the process is running.

Here, the debug client creation from wsdl will generate

 [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) { } ... 

This is how I create a client:

 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; } } 

The generated wsdl code for the AXL API is very large. Both initial and subsequent calls have a CPU problem, although subsequent calls are faster. Is there anything else I can do to debug this problem? Is there a way to reduce this CPU usage?

Update

A bit more info about the bonus:

I created C # classes as follows:

 svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient 

You need to download wsdl for Cisco AXL api from the call manager system. I am using API version 10.5. I believe that the main slowdown is related to XML processing. WSDL for api is huge, as a result of the resulting classes produce 538,406 lines of code!

Update 2

I have enabled WCF tracing with all levels. The biggest time difference is the activity of the process’s action between “The message was written” and “Message sent through the channel”, in which an almost full minute passes between these two actions. Other actions (channel creation, open client base and closed client base) are performed relatively quickly.

Update 3

I made two changes to the generated client classes. First, I removed ServiceKnownTypeAttribute from all operations contracts. Secondly, I removed XmlIncludeAtribute from some serializable classes. These two changes reduced the file size of the generated client by more than 50% and had a small effect on the testing time (reduction of about 10 seconds by the test result of 70 s).

I also noticed that I have approximately 900 work contracts for one service interface and endpoint. This is due to wsdl for the AXL API, which combines all operations in a single namespace. I think about it, but it will mean the creation of several client bases, each of which will implement a reduced interface and eventually break everything that implements this wcf library.

Update 4

It seems that the number of operations is a central issue. I was able to separate operations and definitions of interfaces by verb (for example, gets, adds, etc.) to my client base and interface (a very slow process using sublime text and regular expressions, because resharper and codemaid cannot process a large file, which still 250K + lines). A Get client test with approximately 150 operations installed resulted in a 10 second run for getPhone compared to the previous 60 second result. This is still much slower than it should be, since it is easy to process this operation in the violinist's results in 2 second execution. The solution is likely to further reduce the number of operations by trying to separate operations further. However, this adds a new hacking problem to all systems that used this library as a single client.

+7
c # soap wsdl web-services wcf
source share
1 answer

I finally nailed this problem. The main reason is the number of operations. After breaking the generated client from 900 + operations to 12 each (after specifying this question ), I was able to reduce the processor time spent on generating requests by almost zero.

This is the final process of optimizing a created service client from Cisco AXL wsdl:

Generate client code using wsdl as follows:

 svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient 

Process the generated client file for splitting into child clients:

I created this script to process the generated code. This script does the following:

  • Remove the ServiceKnownType , FaultContract and XmlInclude .

They are useful for processing XML, but the classes you create seem to be wrong from what I understand. For example, the serviceknowntype type is identical for all operations, although many of the known types are unique to each operaiton. This reduces the total size of the generated file from 500K + lines to 250K + with a slight increase in performance at the time of creating the client instance.

  1. Separate work contracts from the interface and methods from the client base that implements the interface.

  2. Create subclients, each of which has 12 operations and their corresponding implementation.

These subclients have three main parts. The first part is a partial class of the original client of the client base. I want this solution to be backward compatible, so I have methods that reference the subclient so that the calls of the old super-client still work, invoking the new subclient. A static get accessor initiates a subclient if it is referenced by any of the implemented operations. Events are also added when close or abort is called so that subclients can perform these operations.

The second and third parts of the subclient are an interface and subclient class that implements 12 operations.

Then I removed the interface and client methods from the original generated client. I replaced the client constructors for the original client to simply store the binding and endpoint data for the subclients that will be used when needed. Closed and interrupted calls were recreated as triggering events that each subclient signed when creating the instance.

Finally, I migrated authentication to endpoint user behavior similar to that described here. Using IClientMessageInspector to send the authentication header immediately saves in a single callback to the server, where WCF prefers to send an anonymous request first before authentication. This gives me about 2 seconds depending on the server.

In general, I have an increase in productivity from 70 to 2.5 seconds.

+1
source share

All Articles