当前位置:  开发笔记 > 编程语言 > 正文

Slow SoapHttpClientProtocol构造函数

如何解决《SlowSoapHttpClientProtocol构造函数》经验,为你挑选了1个好方法。

我正在使用Microsoft Dynamics CRM进行一些实验.您通过Web服务与它进行交互,并且我已将Web引用添加到我的项目中.Web服务接口非常丰富,生成的"Reference.cs"大约是90k loc.

我在控制台应用程序中使用Web引用.我经常改变一些东西,重新编译并运行.编译速度很快,但是新建Web服务引用非常慢,花费大约15-20秒: CrmService service = new CrmService(); 分析显示所有时间都花在SoapHttpClientProtocol构造函数中.

罪魁祸首显然是XML序列化代码(不包括在上面提到的90k loc中)是在运行时生成,然后才进行JIT.这在构造函数调用期间发生.在玩耍和尝试时,等待是相当令人沮丧的.

我尝试了sgen.exe,ngen和XGenPlus的各种组合(需要几个小时并生成500MB的额外代码),但无济于事.我已经考虑过实现一个几乎没有CrmService实例的Windows服务,可以在需要的时候发布,但这似乎太过分了.

有任何想法吗?



1> Chris Marast..:

以下内容是从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提供的有关解决此问题的一些参考:

http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx

不幸的是,上述参考文献均未描述该问题的完整解决方案.相反,他们专注于如何预生成XML序列化代码.

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

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

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

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

跳过步骤2导致该类的实例化时间仅改善20%VimService.跳过步骤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.XmlIncludeAttribute

    并替换为:

    // [System.Xml.Serialization.XmlIncludeAttribute

    这将Xml.Serialization通过评论它们来消除作为减速的最大罪魁祸首的属性.如果您正在使用其他一些.NET语言,只需根据该语言的语法修改替换后的字符串以进行前缀注释.这种简化的方法将为您提供大部分加速.删除剩余的Xml.Serialization属性只能实现0.2秒的额外加速.

    将以下属性添加到VimService.cs中的VimService类:

    [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]

    你应该得到这样的东西:

    // ... Some code here ... [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")] public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol { // ... More code here

    通过重新生成VimSerice.dll库

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

    现在,从您的应用程序中,您可以添加对VimSerice.dll库的引用.

    运行您的应用程序并验证VimService对象的实例化时间是否减少.

补充说明

sgen工具有点像黑盒子,其行为会因Machine.config文件中的内容而异.例如,默认情况下,它应该是优化的非调试代码,但情况并非总是如此.要获得对该工具的一些可见性,请在步骤3中使用/ k标志,这将使其保留所有临时生成的文件,包括它生成的源文件和命令行选项文件.

即使在上述修复之后,第一次实例化VimService类所花费的时间也不是瞬时的(1.5秒).根据经验观察,似乎剩余时间的大部分是由于处理SoapDocumentMethodAttribute属性.目前还不清楚如何减少这个时间.预生成的XmlSerializer程序集不考虑与SOAP相关的属性,因此这些属性需要保留在代码中.好消息是,只有该应用程序的VimService类的第一次实例化需要很长时间.因此,如果额外的1.5秒是一个问题,可以尝试在应用程序开始时对此类进行虚拟实例化,以此作为改善用户登录时间体验的手段.


本周我遇到了完全相同的问题,最初实例化一个Web服务客户端代理需要一段时间.但是,这里有一个重要的问题.当您为Web服务使用的类型注释掉`XmlIncludeAttribute`属性时,客户端将不再知道如何序列化/反序列化这些类型.因此,当您需要向客户端传递或从客户端检索自定义类型时,此选项将不起作用.Microsoft Dynamics CRM服务是一个完美的例子,它不会起作用,因为它包含大量自定义类型.
推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有