C# 慢速SoapHttpClientProtocol构造函数
我正在用Microsoft Dynamics CRM做一些实验。您可以通过web服务与它进行交互,我已经为我的项目添加了一个web引用。web服务界面非常丰富,生成的“Reference.cs”约为90k loc 我正在控制台应用程序中使用web引用。我经常改变一些东西,重新编译并运行。编译速度很快,但更新web服务引用的速度非常慢,大约需要15-20秒:C# 慢速SoapHttpClientProtocol构造函数,c#,.net,performance,xml-serialization,soaphttpclientprotocol,C#,.net,Performance,Xml Serialization,Soaphttpclientprotocol,我正在用Microsoft Dynamics CRM做一些实验。您可以通过web服务与它进行交互,我已经为我的项目添加了一个web引用。web服务界面非常丰富,生成的“Reference.cs”约为90k loc 我正在控制台应用程序中使用web引用。我经常改变一些东西,重新编译并运行。编译速度很快,但更新web服务引用的速度非常慢,大约需要15-20秒: CrmService service=新的CrmService(); 分析显示所有时间都花费在SoapHttpClientProtoco
CrmService service=新的CrmService();
分析显示所有时间都花费在SoapHttpClientProtocol构造函数中
罪魁祸首显然是XML序列化代码(不包括在上面提到的90k loc中)是在JIT’ed之前的运行时生成的。这发生在构造函数调用期间。等待是相当令人沮丧的时候玩和尝试的事情
我尝试了sgen.exe、ngen和XGenPlus的各种组合(这需要几个小时并生成500MB的额外代码),但都没有成功。我曾考虑过实现一个Windows服务,该服务只有很少的CrmService实例可以在需要时提供,但这似乎太过分了
有什么想法吗?您可能希望了解.NET附带的工具。Visual Studio的C#project properties“Build”页面的最底层还有一个很方便的小东西,叫做“Build serialization assembly”,它可以自动为您运行
Sgen
。我相信这不是Sgen的问题。我已经查看了构造函数代码,并且看到它正在进行大量的反射(基于类上的XmlIncludeAttribute)。它会影响所有这些功能,并且可能需要很长时间。CRM附带了一个预生成的XmlSerializer程序集。检查GAC中是否有SdkTypeProxy.XmlSerializers.dll和SdkProxy.XmlSerializers.dll
如果不这样做,则意味着在创建CrmService时,.net将生成XmlSerializer程序集,这可能需要一些时间。
希望这有帮助以下内容摘自VMWare论坛上的线程: 大家好 我们发现sgen.exe确实有效。只是除了预生成序列化程序dll之外,我们在这个线程中错过了几个额外的步骤。这是详细的说明 问题 使用.NET中的VIM 2.0 SDK时,实例化VimService类需要很长时间。(VimService类是通过运行“wsdl.exe vim.wsdl VimService.wsdl”生成的代理类) 换句话说,以下代码行:
_service = new VimService();
可能需要大约50秒来执行
原因
显然,.NETXmlSerializer
使用System.Xml.Serialization.
属性来注释代理类,以在运行时生成序列化代码。当代理类很多且很大时,就像VimService.cs中的代码一样,序列化代码的生成可能需要很长时间
解决方案
这是Microsoft.NET序列化程序工作方式的已知问题
以下是MSDN提供的有关解决此问题的一些参考资料:
不幸的是,上述参考文献都没有描述该问题的完整解决方案。相反,他们关注的是如何预生成XML序列化代码
完整的修复包括以下步骤:
VimService
类的实例化时间缩短20%。跳过步骤1或步骤3会导致错误代码。通过这三个步骤,可实现98%的改进
以下是逐步说明:
开始之前,请确保您正在使用.NET verison 2.0工具。此解决方案不适用于.NET的1.1版,因为sgen工具和XmlSerializationAssemblyAttribute
仅在.NET的2.0版中可用
wsdl.exe vim.wsdl vimService.wsdl
这将输出当前目录中的VimService.cs文件csc/t:library/out:VimService.dll VimService.cs
sgen/p VimService.dll
这将在当前目录中输出VimService.XmlSerializers.dllSystem.Xml.Serialization.*
属性。因为代码很大,所以实现这一点的最佳方法是使用一些正则表达式替换工具。执行此操作时请小心,因为并非所有属性都单独显示在一行上。有些是作为方法声明的一部分排列的
如果您觉得这一步很困难,以下是一种简化的方法:
假设您正在编写C#,请对以下字符串执行全局替换:
[System.Xml.Serialization.xmlcludeAttribute
并将其替换为:
/[System.Xml.Serialization.xmlcludeAttribute
这将通过注释掉Xml.Serialization
属性来消除这些属性,这些属性是导致速度减慢的最大元凶。如果您使用的是其他.NET语言,只需根据该语言的语法将替换的字符串修改为前缀注释。这种简化方法将使您获得c语言的大部分加速get.删除其余的Xml.序列化属性只会获得额外的0.2秒加速this.Proxy = GlobalProxySelection.GetEmptyWebProxy();
REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin
wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
sgen /p references\VIM_Service.dll /force REM generate serializtion dll
(Get-Content VIM.cs) |
ForEach-Object {
$_ -replace "(?<attr>\[global::System.Xml.Serialization.[^\]]*\])", "/*${attr}*/" `
-replace "public partial class VIM", "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""VIM_Service.XmlSerializers"")] `npublic partial class VIM" `
-replace "using System;", "namespace Classes.WS_VIM { `n`nusing System;"
} |
Set-Content VIM.cs
Add-Content VIM.cs "`n}"
cd..\..
generateproxy