- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在使用 WCF 调用 Cisco 的 AXL SOAP API 时,我的 CPU 使用率很高。我首先使用从 wsdl 生成的类创建服务模型客户端库。我正在使用 basichttpbinding 和 transfermode 作为缓冲。执行调用时,CPU 达到极限,CPU 配置文件显示 96% 的 CPU 时间在 _TransparentProxyStub_CrossContext@0
来自 clr.dll,在 base.Channel 等调用之后调用.getPhone(请求);
。更准确地说,该调用使运行该进程的 CPU 内核达到最大。
这是从 wsdl 生成的客户端创建的片段
[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)
{
}
...
这是我创建客户端的方式:
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;
}
}
为 AXL API 生成的 wsdl 代码非常大。初始调用和后续调用都存在 CPU 问题,尽管后续调用速度更快。我还能做些什么来调试这个问题吗?有没有办法降低这种高 CPU 使用率?
更新
有关赏金的更多信息:
我已经像这样创建了 C# 类:
svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient
您必须从调用管理器系统下载 Cisco 的 AXL api 的 wsdl。我使用的是 10.5 版本的 API。我相信主要的减速与 XML 处理有关。 api 的 WSDL 非常庞大,生成的类有 538406 行代码!
更新 2
我已经打开所有级别的 WCF 跟踪。最大的时间差异出现在“已写入消息”和“通过 channel 发送消息”之间的流程操作事件中,这两个操作之间几乎过了整整一分钟。其他事件(构建 channel 、打开客户群和关闭客户群)都执行得相对较快。
更新 3
我对生成的客户端类做了两处更改。首先,我从所有操作契约(Contract)中删除了 ServiceKnownTypeAttribute
。其次,我从一些可序列化的类中删除了 XmlIncludeAtribute。这两项更改将生成的客户端的文件大小减少了 50% 以上,并且对测试时间的影响很小(在 70 秒的测试结果上减少了大约 10 秒)。
我还注意到我有大约 900 个针对单个服务接口(interface)和端点的操作契约(Contract)。这是由于 AXL API 的 wsdl 将所有操作分组在一个命名空间下。我正在考虑将其分解,但这意味着创建多个客户端库,每个客户端库将实现一个简化的接口(interface),并最终破坏实现此 wcf 库的所有内容。
更新 4
看来操作次数是核心问题。我能够通过动词(例如获取、添加等)将操作和接口(interface)定义分离到他们自己的客户端和接口(interface)中(使用 sublime text 和正则表达式的非常缓慢的过程,因为 resharper 和 codemaid 无法处理仍然 250K+ 的大文件线)。对定义了大约 150 个操作的“Get”客户端进行的测试导致 getPhone 的执行时间为 10 秒,而之前的结果为 60 秒。这仍然比它应该的要慢很多,因为在 fiddler 中简单地制作这个操作会导致 2 秒的执行。解决方案可能会通过尝试进一步分离操作来进一步减少操作数。然而,这增加了一个新问题,即破坏所有使用该库作为单个客户端的系统。
最佳答案
我终于解决了这个问题。根本原因似乎确实是操作次数。将生成的客户端从 900 多个操作拆分为 12 个操作(遵循 this question 的指导)后,我能够将生成请求所花费的处理器时间减少到几乎为零。
这是优化从 Cisco 的 AXL wsdl 生成的服务客户端的最终过程:
像这样使用 wsdl 生成客户端代码:
svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient
处理生成的客户端文件以分解为子客户端:
我创建了 this script处理生成的代码。该脚本执行以下操作:
ServiceKnownType
、FaultContract
和 XmlInclude
属性。 这些对于 xml 处理很有用,但据我所知,生成的类似乎不正确。例如,服务已知类型对于所有操作都是相同的,即使许多已知类型对于每个操作都是唯一的。这将生成的文件的总大小从 500K+ 行减少到 250K+,客户端实例化时间的性能略有增加。
将接口(interface)和方法的操作契约与实现该接口(interface)的客户端分开。
创建子客户端,每个子客户端有 12 个操作及其各自的实现。
这些子客户端具有三个主要部分。第一部分是原始 clientbase 客户端的部分类。我希望这个解决方案向后兼容,所以我在这里有引用子客户端的方法,这样通过调用新的子客户端,对旧 super 客户端的调用仍然有效。如果引用了任何已实现的操作,静态获取访问器将启动子客户端。还为调用关闭或中止时添加了事件,以便子客户端仍然可以运行这些操作。
子客户端的第二部分和第三部分是实现12个操作的接口(interface)和子客户端类。
然后我从原始生成的客户端中删除了接口(interface)和客户端方法。我替换了原始客户端的客户端构造函数,以简单地存储绑定(bind)和端点数据供子客户端在需要时使用。关闭和中止调用被重新创建为每个子客户端在实例化时都会订阅的事件调用程序。
最后,我将身份验证移至类似于 described here 的自定义端点行为.使用 IClientMessageInspector
立即发送身份验证 header 可以节省对服务器的一次往返调用,WCF 喜欢在服务器进行身份验证之前先发送匿名请求。这使我大约增加了 2 秒,具体取决于服务器。
总体而言,我的性能从 70 秒提高到 2.5 秒。
关于c# - WCF 在调用期间等待 _TransparantProxyStub_CrossContext 函数时使 CPU 最大化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35761583/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!