C# 慢速SoapHttpClientProtocol构造函数

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

我正在用Microsoft Dynamics CRM做一些实验。您可以通过web服务与它进行交互,我已经为我的项目添加了一个web引用。web服务界面非常丰富,生成的“Reference.cs”约为90k loc

我正在控制台应用程序中使用web引用。我经常改变一些东西,重新编译并运行。编译速度很快,但更新web服务引用的速度非常慢,大约需要15-20秒:

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秒来执行

原因 显然,.NET
XmlSerializer
使用
System.Xml.Serialization.
属性来注释代理类,以在运行时生成序列化代码。当代理类很多且很大时,就像VimService.cs中的代码一样,序列化代码的生成可能需要很长时间

解决方案 这是Microsoft.NET序列化程序工作方式的已知问题

以下是MSDN提供的有关解决此问题的一些参考资料:

不幸的是,上述参考文献都没有描述该问题的完整解决方案。相反,他们关注的是如何预生成XML序列化代码

完整的修复包括以下步骤:

  • 使用预生成的XML序列化程序代码创建程序集(DLL)

  • 从代理代码(即从VimService.cs文件)中删除对System.Xml.Serialization.*属性的所有引用

  • 使用XmlSerializerAssemblyAttribute注释主代理类,以将其指向XML序列化程序集所在的位置

  • 跳过步骤2只会使
    VimService
    类的实例化时间缩短20%。跳过步骤1或步骤3会导致错误代码。通过这三个步骤,可实现98%的改进

    以下是逐步说明:

    开始之前,请确保您正在使用.NET verison 2.0工具。此解决方案不适用于.NET的1.1版,因为sgen工具和
    XmlSerializationAssemblyAttribute
    仅在.NET的2.0版中可用

  • 使用WSDL.exe从WSDL生成VimService.cs文件:

    wsdl.exe vim.wsdl vimService.wsdl

    这将输出当前目录中的VimService.cs文件

  • 将VimService.cs编译到库中

    csc/t:library/out:VimService.dll VimService.cs

  • 使用sgen工具预生成和编译XML序列化程序:

    sgen/p VimService.dll

    这将在当前目录中输出VimService.XmlSerializers.dll

  • 返回VimService.cs文件并删除所有
    System.Xml.Serialization.*
    属性。因为代码很大,所以实现这一点的最佳方法是使用一些正则表达式替换工具。执行此操作时请小心,因为并非所有属性都单独显示在一行上。有些是作为方法声明的一部分排列的

    如果您觉得这一步很困难,以下是一种简化的方法:

    假设您正在编写C#,请对以下字符串执行全局替换:

    [System.Xml.Serialization.xmlcludeAttribute

    并将其替换为:

    /[System.Xml.Serialization.xmlcludeAttribute

    这将通过注释掉
    Xml.Serialization
    属性来消除这些属性,这些属性是导致速度减慢的最大元凶。如果您使用的是其他.NET语言,只需根据该语言的语法将替换的字符串修改为前缀注释。这种简化方法将使您获得c语言的大部分加速get.删除其余的Xml.序列化属性只会获得额外的0.2秒加速

  • 将以下属性添加到VimServic
    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